Haskell 文献中列表单子绑定的两种实现:为什么它们是等价的?
阅读Graham Hutton第二版“Haskell中的编程”中的Monad一章,我在第167页找到了这个例子来说明列表Monad的行为:Haskell 文献中列表单子绑定的两种实现:为什么它们是等价的?,haskell,Haskell,阅读Graham Hutton第二版“Haskell中的编程”中的Monad一章,我在第167页找到了这个例子来说明列表Monad的行为: > pairs [1,2] [3,4] [(1,3),(1,4),(2,3),(2,4)] 对的定义如下: pairs :: [a] -> [b] -> [(a,b)] pairs xs ys = do x <- xs y <- ys return (
> pairs [1,2] [3,4]
[(1,3),(1,4),(2,3),(2,4)]
对的定义如下:
pairs :: [a] -> [b] -> [(a,b)]
pairs xs ys = do x <- xs
y <- ys
return (x,y)
有了这个定义,我理解了这个例子为什么有效。
但第一个定义是我在《序曲》中找到的,所以我相信它是正确的
我的问题:
- 有人能解释为什么第一个定义等同于第二个定义吗?(第一节中的concat发生在哪里?)
- 列表理解只是句法上的糖分。基本上,
[fxy | x>=\y->返回(x,y)
≡ [p | x>=\y->返回(ξ,y))x]
≡ [p | x=\y->返回(x,y))]
≡ [p|x[y | x>=f
太多了…我现在不得不慢慢咀嚼:-)但现在我意识到我对列表理解的理解太幼稚了:这真是一头野兽。谢谢你…现在我了解到列表理解中有一个隐含的concat。注意列表理解是单子理解的一个特例,它是do表示法的一种特殊语法,它是>=
的特殊语法,在引擎盖下使用join
。“隐式concat”通常是一元join::Monad m=>m(MA)->m a
。是的,但是解释>=
在理解和解释do
-符号和>=
方面是有点循环的。@Lazersmoke确实-(>=f)=join.fmap f
与此相关。为了避免混淆,还值得一提的是,就目前情况来看,(>=)
并没有真正地在引擎盖下使用join
(当然也可以这样实现)。join x
目前定义为x>=id
@duplode我的意思是澄清一下“在引擎盖下”的意思是,join
是monad的理论基础操作,>=
只是定义它的一种很好的等效方法(使用标识join=(>>=id)
)
instance Monad [] where
-- (>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = [y | x <- xs, y <- f x]
...
xs >>= f = concat (fmap f xs)
concatMap (\x -> concatMap (\y -> return $ f x y) m) l
concat $ fmap (\x -> concat $ fmap (\y -> return $ f x y) m) l
pairs [1,2] [3,4]
≡ do { x <- [1,2]; y <- [3,4]; return (x,y) }
≡ [1,2] >>= \x -> [3,4] >>= \y -> return (x,y)
≡ [p | x<-[1,2], p <- (\ξ -> [3,4] >>= \y -> return (ξ,y)) x]
≡ [p | x<-[1,2], p <- ([3,4] >>= \y -> return (x,y))]
≡ [p | x<-[1,2], p <- [q | y<-[3,4], q <- (\υ -> return (x,υ)) y]]
≡ [p | x<-[1,2], p <- [q | y<-[3,4], q <- return (x,y)]]
≡ [p | x<-[1,2], p <- [q | y<-[3,4], q <- [(x,y)]]]
≡ [p | x<-[1,2], p <- [(x,3), (x,4)]]
≡ [(1,3), (1,4)] ++ [(2,3), (2,4)]
≡ [(1,3), (1,4), (2,3), (2,4)]