我很难理解以下代码(在 IO 之上的 ErrorT monad 中执行):
closePort [Port port] = liftIO $ hClose port >> (return $ Bool True)
>>
的优先级高于$
。那么是Bool True
首先包裹在 IO 中,然后是先提升liftIO
还是hClose
先提升?换句话说,是在 IO monad 还是在 ErrorT monad 中执行>>
?return
我很难理解以下代码(在 IO 之上的 ErrorT monad 中执行):
closePort [Port port] = liftIO $ hClose port >> (return $ Bool True)
>>
的优先级高于$
。那么是Bool True
首先包裹在 IO 中,然后是先提升liftIO
还是hClose
先提升?换句话说,是在 IO monad 还是在 ErrorT monad 中执行>>
?return
在这种情况下,您实际上不必担心优先级,因为
liftIO (hClose port >> return (Bool True))
和
liftIO (hClose port) >> return (Bool True)
由于单子变换定律,它必须是等价的,它说
起重return
没有任何作用。
lift . return = return
举起两个动作的序列与分别举起它们相同。
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
。所以(>>)
andreturn
是 的IO
,然后整个IO
-computation 被提升liftIO
。
(我假设Bool
这里是您定义的类型的数据构造函数。)
liftIO $ hClose port >> (return $ Bool True)
是相同的
liftIO (hClose port >> (return (Bool True)))
所以 thereturn
和 the>>
都是IO
版本,并且 the 的结果>>
被提升到外部 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))
所以首先hClose
andreturn $ Bool True
被组合成一个带有 type 的表达式,IO (Bool')
然后用liftIO
. Bool'
(无论类型在哪里Bool True
)。
Haskell 报告对语法进行了彻底的处理,尤其是第 2、3 和 9 章。
您可能想查看以下内容的实现$
:
($) :: (a -> b) -> a -> b
f $ x = f x
这意味着,x
如果需要,将对其进行评估f
。在那之前,我们有
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) ))
我希望能澄清它。