列表理解风格中给出了一个功能
f1 :: [Int] -> [Int] -> [Int]
f1 xs ys = [ x+y | x <- xs, y <-ys ]
那并不复杂。 示例输出:
*主&GT; 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
。
第一个列表的每个元素都将添加到另一个列表中的每个元素。
答案 0 :(得分:4)
我不是直接给出这个家庭作业的解决方案,而是用更一般的术语解释它。你现在可能不太了解它,但至少应该能够找出你需要的东西!
map
只是&{34;促进&#34;的Functor
方法的专用版本(用于列表仿函数)。函数函数的函数:
class Functor f where
fmap :: (a->b) -> f a->f b
现在,列表是一种特别强大的仿函数: applicative 仿函数,甚至是monad。 Applicative
让许多程序员感到困惑,但你的例子非常合适:
前奏&GT; :m + Control.Applicative
Prelude Control.Applicative&gt;设f1 xs ys =(+)&lt; $&gt; xs&lt; *&gt; YS
Prelude Control.Applicative&gt; :t f1
f1 ::(Num b,Applicative f)=&gt; f b - &gt; f b - &gt; f b
Prelude Control.Applicative&gt; 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&gt; (+)&lt; $&gt; [1,2,3,4]&lt; *&gt; [5,6,7,8]
[6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12]
看起来很简单,但这是如何工作的?关于Applicative
类的令人困惑的是,你继续将curried函数插入到functor中,在那里部分评估它们,并以某种方式从外部检索结果。对于monad,你不能这样做,所以他们可以更容易掌握。仅使用Monad
类型类,也可以执行示例(Monad
严格地比Applicative
更严格。
Haskell列表的理解实际上只是monad操作的语法糖!
[ x+y | x <- xs, y <- ys ]
是糖的
xs >>= \x -> ys >>= \y -> return (x+y)
或附加括号:
xs >>= ( \x -> ( ys >>= ( \y -> return (x+y) ) ) )
好吧,您可以使用以下规则转换为仅包含map
和concat
的内容:
ys >>= (\y -> return (f y))
与map f ys
相同。zs >>= (\z -> g z)
与concat (map g zs)
相同。答案 1 :(得分:2)
一种方式是:
f1 xs ys = concat $ map (\x -> map (\y -> x + y) ys) xs
ghci中的演示:
λ> 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]
答案 2 :(得分:1)
[ x+y | x <- xs, y <-ys ]
与
相同do {x <- xs; y <- ys; return (x + y)}
与
相同xs >>= \x -> ys >>= \y -> return (x + y)
>>=
被称为bind。这里使用的是着名的monad列表。对于列表,返回定义为return x = [x]
,绑定定义为xs >>= f = concatMap f xs
,顾名思义,concatMap
只是concat
和{{1}的组合}。
列表monad背后的想法是,使用map
,您不确定地选择列表中的某个任意元素,然后使用它进行一些计算,最后,您将获得所有可能结果的列表得到。所以在你的例子中,
x <- xs
分别从do {x <- xs; y <- ys; return (x + y)}
和x
选择y
和xs
,并获得所有可能结果的列表。
现在,我将让您使用此知识将列表理解转换为仅使用ys
和map
的表达式。
对于concat
,列表推导中的条件filter
会转换为列表monad中的b
,如果您想要非guard b
,则可以用filter
表示 - 单词表达。
答案 3 :(得分:0)
通用列表理解的格式为
[ e | qual1 , qual2 , ... , qualN ]
其中e
是表达式,qual
是限定符。限定符可以有三种形式:生成器(x<-list
),布尔警卫(x/=0
)和本地声明(let x = ...
)。由于你只使用发电机,我将专注于那些。
根据Haskell definition,列表汇总可以翻译如下
[ e | x<-l , quals ] = concat $ map (\x -> [ e | quals ]) l
[ e | ] = [ e ] -- singleton list
所以你可以将这些应用到[ x+y | x <- xs, y <-ys ]
并获得解决方案(基本上就是Sibi的答案)。