use*_*115 1 haskell list-comprehension higher-order-functions
有一个以列表理解风格给出的函数
f1 :: [Int] -> [Int] -> [Int]
f1 xs ys = [ x+y | x <- xs, y <-ys ]
Run Code Online (Sandbox Code Playgroud)
那没那么复杂。示例输出:
*主> f2 [1,2,3,4] [5,6,7,8]
[6,7,8,9,7,8,9,10,8,9,10,11,9,10 ,11,12]
任务是转换这个函数和其他几个函数,只使用map,filter和concat。其他函数没有问题,但我不知道如何解决map这里的嵌套。第一个列表的每个元素都将添加到另一个列表中的每个元素。
我不会直接给出这个作业的解决方案,而是用更一般的术语来解释它。您现在可能不了解其中的大部分内容,但至少应该能够挑选出您需要的内容!
map只是将函数Functor“提升”为函子函数的方法的专用版本(对于列表函子):
class Functor f where
fmap :: (a->b) -> f a->f b
Run Code Online (Sandbox Code Playgroud)
现在,列表是一种特别强大的函子:一个应用函子,甚至是一个 monad。Applicative使许多程序员感到困惑,但您的示例非常适合:
Prelude> :m +Control.Applicative
Prelude Control.Applicative> 让 f1 xs ys = (+) <?$> xs <?*> ys
Prelude Control.Applicative> :t f1
f1 :: (Num b, Applicative f) = > fb -> fb -> fb
Prelude Control.Applicative> f1 [1,2,3,4] [5,6,7,8]
[6,7,8,9,7,8,9,10,8 ,9,10,11,9,10,11,12]
当然你也可以简单的写
Prelude Control.Applicative> (+) <?$> [1,2,3,4] <*> [5,6,7,8]
[6,7,8,9,7,8,9,10, 8,9,10,11,9,10,11,12]
看起来很简单,但这是如何工作的?Applicative该类的令人困惑之处在于,您不断将柯里化函数放入函子中,在那里对它们进行部分评估,并以某种方式从外部检索结果。使用 monad,你不会这样做,所以它们更容易掌握。仅使用Monad类型类,示例也可以完成(Monad严格比Applicative)。
Haskell 列表推导式实际上只是 monad 操作的语法糖!
[ x+y | x <- xs, y <- ys ]
Run Code Online (Sandbox Code Playgroud)
糖是为了
xs >>= \x -> ys >>= \y -> return (x+y)
Run Code Online (Sandbox Code Playgroud)
或额外的括号:
xs >>= ( \x -> ( ys >>= ( \y -> return (x+y) ) ) )
Run Code Online (Sandbox Code Playgroud)
好了,这个你可以改变的东西,只有map和concat使用这些规则:
ys >>= (\y -> return (f y))与 相同map f ys。zs >>= (\z -> g z)与 相同concat (map g zs)。