繁体   English   中英

理解Haskell中的$

[英]Understanding $ in Haskell

我在理解以下代码时遇到了一些困难(在IO顶层的ErrorT monad中执行):

closePort [Port port] = liftIO $ hClose port >> (return $ Bool True)

>>具有比$更高的优先级。 Bool True首先包含在IO中,而不是使用liftIO解除,还是hClose解除hClose 换句话说>>return在IO monad或ErrorT monad中执行?

在这种情况下,您不必担心优先级,因为

liftIO (hClose port >> return (Bool True))

liftIO (hClose port) >> return (Bool True)

由于monad变压器定律,它必须是等价的

  1. 提升return什么都不做。

     lift . return = return 
  2. 提升两个动作的顺序与单独提升它们相同。

     lift (m >>= f) = lift m >>= (lift . f) 

liftIO也应该遵循这些法律,所以我们可以看到

liftIO (hClose port >> return (Bool True))
= -- definition of >>
liftIO (hClose port >>= \_ -> return (Bool True))
= -- second monad transformer law
liftIO (hClose port) >>= \_ -> liftIO (return (Bool True))
= -- first monad transformer law
liftIO (hClose port) >>= \_ -> return (Bool True)
= -- definition of >>
liftIO (hClose port) >> return (Bool True)

给定的代码相当于

closePort [Port port] = liftIO ( hClose port >> (return ( Bool True) ) )

所以整个(hClose port) >> (return (Bool True))liftIO的参数。 所以(>>)returnIO ,然后用liftIO解除整个IO liftIO

(我假设Bool在这里是你定义的类型的数据构造函数。)

liftIO $ hClose port >> (return $ Bool True)

是相同的

liftIO (hClose port >> (return (Bool True)))

因此return>>都是IO版本, >>的结果被提升到外部monad中。

具有较高优先级的运算符比具有低优先级的运算符绑定得更紧密。

要计算出多个运算符在表达式中时的排序,请从最高优先级运算符开始,并在两侧的表达式周围加上括号,然后通过运算符优先级继续向下。 对于同级别的操作员,您可以根据其定义的关联性确定订单。 混合具有相同优先级但不同的关联行为的运算符是非法的,因为分组是不明确的。 使用数字运算符可能很熟悉这个过程:

2 + 3 * 5 - 1 + 2
-- * is infixl 7
2 + (3 * 5) - 1 + 2
-- + and - are infixl 6, so apply parens starting at the left
(2 + (3 * 5)  - 1) + 2

((2 +(3 * 5)) - 1)+ 2

由于>>的优先级高于$ ,因此应用相同的处理方法

liftIO $ hClose port >> (return $ Bool True)

给你

liftIO $ (hClose port >> (return $ Bool True))

所以首先将hClosereturn $ Bool True组合成一个类型为IO (Bool')的表达式,然后用liftIO解除。 Bool'Bool True任何类型)。

Haskell报告提供了对语法的彻底处理,特别是第2,3和9章。

您可能想看看$的实现:

($) :: (a -> b) -> a -> b
f $ x = f x

这意味着,如果f需要,将评估x 在那之前,我们有

f $ expression for x = f (expression for x)

在你的情况下,我们有

x = hClose port >> (return ( Bool True) )
f = liftIO

这意味着

f $ expression for x = f (expression for x)
                     = liftIO (expression for x)
                     = liftIO (hClose port >> (return ( Bool True) ))

我希望澄清一下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM