我在理解以下代码时遇到了一些困难(在IO之上的一个ErrorT monad中执行):
closePort [Port port] = liftIO $ hClose port >> (return $ Bool True)
>>
的优先级高于$
。那么Bool True
首先包含在IO中,而不是首先提升liftIO
或hClose
?换句话说,在IO monad或ErrorT monad中执行>>
和return
?
答案 0 :(得分:14)
在这种情况下,您不必担心优先级,因为
liftIO (hClose port >> return (Bool True))
和
liftIO (hClose port) >> return (Bool True)
由于monad变压器定律,必须等效
提升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)
答案 1 :(得分:7)
给定代码相当于
closePort [Port port] = liftIO ( hClose port >> (return ( Bool True) ) )
因此整个(hClose port) >> (return (Bool True))
是liftIO
的参数。因此,(>>)
和return
是IO
的{{1}},然后整个IO
- 计算会被liftIO
解除。
答案 2 :(得分:1)
(我假设Bool
这里是你定义的类型的数据构造函数。)
liftIO $ hClose port >> (return $ Bool True)
与
相同liftIO (hClose port >> (return (Bool True)))
因此return
和>>
都是IO
版本,而>>
的结果会被提升到外部monad中。
答案 3 :(得分:1)
具有更高优先级的运算符比具有低优先级的运算符绑定得更紧密。
要计算出多个运算符在表达式中的顺序,请从最高优先级运算符开始,并在两侧的表达式周围加上括号,然后通过运算符优先级继续向下。对于同级别的操作员,您可以根据其定义的关联性确定订单。混合具有相同优先级但不同的关联行为的运算符是非法的,因为分组是不明确的。使用数值运算符可能很熟悉这个过程:
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
和return $ Bool True
合并为一个类型为IO (Bool')
的表达式,然后用liftIO
解除。 (Bool'
是Bool True
所具有的任何类型。
Haskell Report提供了语法的全面处理,特别是第2,3和9章。
答案 4 :(得分:-2)
您可能希望查看$
的实现:
($) :: (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) ))
我希望澄清它。