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 ]