阅读“Haskell编程”第2版中的Monad章节。来自Graham Hutton,我在第167页找到了这个例子来说明List Monad的行为:
pairs :: [a] -> [b] -> [(a,b)]
pairs xs ys = do x <- xs
y <- ys
return (x,y)
对象定义如下:
instance Monad [] where
-- (>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = [y | x <- xs, y <- f x]
这个bind的实现:
...
xs >>= f = concat (fmap f xs)
我试着用铅笔和纸来理解这个例子是如何解决的,但是没有得到它。
然后我发现,在其他书中,绑定操作的定义不同:
{{1}}
通过这个定义,我理解为什么这个例子有效。 但第一个定义是我在前奏中发现的hackage,所以我相信它是正确的。
我的问题:
答案 0 :(得分:2)
列表理解只是语法糖。基本上,[f x y | x<-l, y<-m]
是糖的
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)]
答案 1 :(得分:0)
[y | x <- xs, y <- f x]
逐个接受x
中的所有xs
和
f
应用于他们,这是一个monadic操作a -> [a]
,因此结果是一个值列表([a]
)y
逐一解决每个f x
y
都会发送到输出列表这相当于首先在输入列表的每个元素上映射f
,从而生成嵌套列表的列表,然后将其连接起来。请注意,列表中fmap
为map
,您可以使用concatMap f xs
作为xs >>= f
的定义。