List Haskell Monad-列表中的Monad是如何工作的?
为了理解Monad,我提出了以下定义:List Haskell Monad-列表中的Monad是如何工作的?,list,haskell,monads,List,Haskell,Monads,为了理解Monad,我提出了以下定义: class Applicative' f where purea :: a -> f a app :: f (a->b) -> f a -> f b class Applicative' m => Monadd m where (>>|) :: m a -> (a -> m b) -> m b instance Applicative' [] where purea x = [x]
class Applicative' f where
purea :: a -> f a
app :: f (a->b) -> f a -> f b
class Applicative' m => Monadd m where
(>>|) :: m a -> (a -> m b) -> m b
instance Applicative' [] where
purea x = [x]
app gs xs = [g x | g <- gs, x <- xs]
instance Monadd [] where
(>>|) xs f = [ y | x <-xs, y <- f x]
但我不确定它是如何工作的。
例如:
[ y | y <- [[1],[2]]]
[[1],[2]]
[y | y([x+1])
到[1,2,3]
的每个列表元素会导致[2,3,4]
而不是[2]、[3]、[4]
或者很简单,我的困惑似乎源于不理解“数学定义”如何比Haskell标准类的方法更容易理解这条语句
class Applicative' m => Monadd m where
join :: m (m a) -> m a
请注意,您可以在此方面实施标准版本,反之亦然:
join mma = mma >>= id
ma >>= f = join (fmap f ma)
对于列表,join
(也称为concat
)特别简单:
join :: [[a]] -> [a]
join xss = [x | xs <- xss, x <- xs] -- xss::[[a]], xs::[a]
-- join [[1],[2]] ≡ [1,2]
、和更多描述单子列表
比较:
用于具有(=mb)->ma->mb
- 对于
m=[]
(>>=)
绑定操作符的参数是翻转的,但在其他方面,它只是一个中缀concatMap
或者很简单,我的困惑似乎源于不理解这句话实际上是如何运作的:
(>>|) xs f = [ y | x <- xs, y <- f x ]
实例Monadd[]
,而不依赖现有的Monad实例或列表理解:
- 使用
:concatMap
instance Monadd [] where (>>|) xs f = concatMap f xs
- 再详细说明一下:
instance Monadd [] where (>>|) xs f = concat (map f xs)
- 更详细地说:
instance Monadd [] where (>>|) [] f = [] (>>|) (x:xs) f = let ys = f x in ys ++ ((>>|) xs f)
return
的内容。我不知道为什么会缺少它。就像嵌套循环一样:
xs >>| foo = [ y | x <- xs, y <- foo x]
-- = for x in xs:
-- for y in (foo x):
-- yield y
以上相当于
concat (map foo [a,b,c,d])
=
foo a ++ foo b ++ foo c ++ foo d
对于一些适当的foo
concat
是列表单子的join
,map
是列表单子的fmap
。通常,对于任何单子
m >>= foo = join (fmap foo m)
单子的本质是:从“结构”中的每个“实体”,有条件地在同一种结构中产生新元素,并将它们拼接到位:
[ a , b , c , d ]
/ \ | | / \
[ [a1, a2] , [b1] , [] , [d1, d2] ] -- fmap foo = [foo x | x <- xs]
-- = [y | x <- xs, y <- [foo x]]
[ a1, a2 , b1 , d1, d2 ] -- join (fmap foo) = [y | x <- xs, y <- foo x ]
[a,b,c,d]
/ \ | | / \
[a1,a2],[b1],[d1,d2]——fmap foo=[foo x | x你自己写的。(>>|)xs f=[y | x是的,看起来我不明白如何[y | x在这个表达式中写下x、xs、y和fx的类型应该是有帮助的。但是在我定义的Applicative
和Monadd
实例中,它是如何工作的?或者更确切地说,join
是如何在purea
app
和中实现的
?好吧,通过加入elementwise应用结果。我想你没有意识到列表理解可以做到这一点(参见编辑,我展示了如何通过理解来实现加入
)。虽然没有作弊。LCs恰好与一元代码等效,但是。
instance Monadd [] where
(>>|) [] f = []
(>>|) (x:xs) f = let ys = f x in ys ++ ((>>|) xs f)
xs >>| foo = [ y | x <- xs, y <- foo x]
-- = for x in xs:
-- for y in (foo x):
-- yield y
[1,2,3,4] >>| (\x -> [x, x+10])
=
[ y | x <- [1,2,3,4], y <- (\x -> [x, x+10]) x]
=
[ y | x <- [1] ++ [2,3,4], y <- [x, x+10]]
=
[ y | x <- [1], y <- [x, x+10]] ++ [ y | x <- [2,3,4], y <- [x, x+10]] -- (*)
=
[ y | y <- [1, 1+10]] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[ y | y <- [1]] ++ [ y | y <- [11]] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[1] ++ [11] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [ y | x <- [3,4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [3, 13] ++ [ y | x <- [4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [3, 13] ++ [4, 14]
[ a, [a1, a2] ++ concat [ [a1, a2], [ a1, a2,
b, ==> [b1] ++ == [b1], == b1,
c, [] ++ [],
d ] [d1, d2] [d1, d2] ] d1, d2 ]
concat (map foo [a,b,c,d])
=
foo a ++ foo b ++ foo c ++ foo d
m >>= foo = join (fmap foo m)
[ a , b , c , d ]
/ \ | | / \
[ [a1, a2] , [b1] , [] , [d1, d2] ] -- fmap foo = [foo x | x <- xs]
-- = [y | x <- xs, y <- [foo x]]
[ a1, a2 , b1 , d1, d2 ] -- join (fmap foo) = [y | x <- xs, y <- foo x ]