Haskell Monad-列表中的Monad如何工作? [英] Haskell Monad - How does Monad on list work?
问题描述
为了理解Monad,我提出了以下定义:
In order to understand Monad, I came up with the following definitions:
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]
它按预期工作:
(>>|) [1,2,3,4] (\x->[(x+1)])
[2,3,4,5]
我不确定它是如何工作的. 例如:
I am not sure how it is working though. For example:
[ y | y <- [[1],[2]]]
[[1],[2]]
对[1,2,3]
的每个列表元素的应用程序(\x->([x+1])
如何导致[2,3,4]
而不是[[2],[3],[4]]
How does application (\x->([x+1])
to each list element of [1,2,3]
result in [2,3,4]
and not [[2],[3],[4]]
或者很简单地,我的困惑似乎是由于不了解该语句[ y | x <-xs, y <- f x]
的实际工作方式
Or quite simply my confusion seems to stem from not understanding how this statement [ y | x <-xs, y <- f x]
actually works
推荐答案
哈斯克尔学校, LYAH , Quora 以及更多描述单子的列表.
Wadler, School of Haskell, LYAH, HaskellWiki, Quora and many more describe the list monad.
比较:
-
(=<<) :: Monad m => (a -> m b) -> m a -> m b
用于具有 的列表
-
concatMap :: (a -> [b]) -> [a] -> [b]
用于m = []
.
(=<<) :: Monad m => (a -> m b) -> m a -> m b
for lists withconcatMap :: (a -> [b]) -> [a] -> [b]
form = []
.
常规的(>>=)
绑定运算符的参数已翻转,但否则只是一个后缀concatMap
.
The regular (>>=)
bind operator has the arguments flipped, but is otherwise just an infix concatMap
.
或者很简单地,我的困惑似乎是由于不了解该语句的实际工作原理而产生的:
Or quite simply my confusion seems to stem from not understanding how this statement actually works:
(>>|) xs f = [ y | x <- xs, y <- f x ]
由于列表推导与列表的Monad实例等效,因此此定义是一种作弊行为.基本上,您说的是某种东西,就像它是Monad一样,是Monadd,所以剩下两个问题:了解列表推导和仍然了解Monad.
Since list comprehensions are equivalent to the Monad instance for lists, this definition is kind of cheating. You're basically saying that something is a Monadd in the way that it's a Monad, so you're left with two problems: Understanding list comprehensions, and still understanding Monad.
可以理解列表的理解力,以便更好地理解:
List comprehensions can be de-sugared for a better understanding:
对于您而言,该语句可以用多种其他方式编写:
In your case, the statement could be written in a number of other ways:
-
使用符号:
Using do-notation:
(>>|) xs f = do x <- xs
y <- f x
return y
建议使用(>>=)
运算符:
De-sugared into using the (>>=)
operator:
(>>|) xs f = xs >>= \x ->
f x >>= \y ->
return y
这可以缩短(每行重写一次):
This can be shortened (one rewrite per line):
(>>|) xs f = xs >>= \x -> f x >>= \y -> return y -- eta-reduction
≡ (>>|) xs f = xs >>= \x -> f x >>= return -- monad identity
≡ (>>|) xs f = xs >>= \x -> f x -- eta-reduction
≡ (>>|) xs f = xs >>= f -- prefix operator
≡ (>>|) xs f = (>>=) xs f -- point-free
≡ (>>|) = (>>=)
因此,通过使用列表推导,您尚未真正声明一个新的定义,而是仅依赖现有的定义.如果需要,您可以定义instance Monadd []
而不依赖现有的Monad实例或列表理解:
So from using list comprehensions, you haven't really declared a new definition, you're just relying on the existing one. If you wanted, you could instead define your instance Monadd []
without relying on existing Monad instances or list comprehensions:
-
使用
concatMap
:
instance Monadd [] where
(>>|) xs f = concatMap f xs
进一步说明:
Spelling that out a little more:
instance Monadd [] where
(>>|) xs f = concat (map f xs)
进一步说明:
Spelling that out even more:
instance Monadd [] where
(>>|) [] f = []
(>>|) (x:xs) f = let ys = f x in ys ++ ((>>|) xs f)
Monadd类型类应具有与return
类似的内容.我不确定为什么会丢失它.
The Monadd type class should have something similar to return
. I'm not sure why it's missing.
这篇关于Haskell Monad-列表中的Monad如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!