List 如何使用bind(>;>;=)实现函数

List 如何使用bind(>;>;=)实现函数,list,haskell,monads,List,Haskell,Monads,我写了一个过滤函数: f :: (a -> Bool) -> [a] -> [a] f p xs = case xs of [] -> [] x : xs' -> if p x then x : f p xs' else f p xs' 为了理解bind,我想使用bind实现它。 我在想什么: f p xs = xs >>= (\x xs

我写了一个过滤函数:

f :: (a -> Bool) -> [a] -> [a]
f p xs = case xs of
         [] -> []
         x : xs' -> if p x
                    then x : f p xs'
                    else f p xs'
为了理解bind,我想使用bind实现它。 我在想什么:

f p xs = xs >>= (\x xs -> if p x then x : f p xs else f p xs)
但我得到了这个错误:

* Couldn't match expected type `[a]' with actual type `[a] -> [a]'
    * The lambda expression `\ x xs -> ...' has two arguments,
      but its type `a -> [a]' has only one
      In the second argument of `(>>=)', namely
        `(\ x xs -> if p x then x : f p xs else f p xs)'
      In the expression:
        xs >>= (\ x xs -> if p x then x : f p xs else f p xs)
    * Relevant bindings include
        xs :: [a] (bound at <interactive>:104:5)
        p :: a -> Bool (bound at <interactive>:104:3)
        f :: (a -> Bool) -> [a] -> [a] (bound at <interactive>:104:1)
怎么了

为了理解bind,我想将其实现为bind

这里没有束缚。如果出现错误,将添加绑定。上面的表达式不是do表达式,因此这里没有绑定

但是,您可以使用bind编写此代码,如:

f p xs = xs >>= \x -> if p x then [x] else []

但这不是原始函数的文本映射,我们只是在这里使用
实例Monad[]
实现。然而,您的
f
就在这里。

要理解bind,首先实现no-op:

当然,对于列表

[x]       ==  return x
[x | p x] ==  if p x then return x else mzero
mzero     ==  []
concat    ==  join
这使我们回到一种显式递归的方式,将
filter
编码为

filter p []     =  []
filter p (x:xs) =  [x | p x] ++ filter p xs
使用bind,我们考虑将列表中的每个元素分别转换为该输入元素的结果列表(无、一个或多个)。基于
foldr
的代码破坏了这一点


所以,代码本身就是

filter_bind p xs  =  xs  >>=  (\x -> [x | p x])
因为我们有

xs >>= f  ==  join (fmap f xs) 
          ==  concat (map f xs) 
          ==  concat [ f x | x <- xs ]
          ==  foldr (++) []
                     [ f x | x <- xs ]
xs>>=f==join(fmap f xs)
==concat(映射f xs)

==concat[f x | x这不是
do
块,因此此处不使用绑定。列表绑定
>=
concatMap
,而不是
foldr
[x]       ==  return x
[x | p x] ==  if p x then return x else mzero
mzero     ==  []
concat    ==  join
filter p []     =  []
filter p (x:xs) =  [x | p x] ++ filter p xs
filter_bind p xs  =  xs  >>=  (\x -> [x | p x])
xs >>= f  ==  join (fmap f xs) 
          ==  concat (map f xs) 
          ==  concat [ f x | x <- xs ]
          ==  foldr (++) []
                     [ f x | x <- xs ]