Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Haskell中映射多个参数上的函数列表?_Haskell_Currying - Fatal编程技术网

如何在Haskell中映射多个参数上的函数列表?

如何在Haskell中映射多个参数上的函数列表?,haskell,currying,Haskell,Currying,我有三个函数(getRow,getColumn,getBlock),它们有两个参数(x和y),每个参数都生成相同类型的列表。我想写第四个函数来连接它们的输出: outputList :: Int -> Int -> [Maybe Int] outputList x y = concat . map ($ y) $ map ($ x) [getRow,getColumn,getBlock] 该函数可以工作,但是有没有办法将双映射(带有三个“$”的)重写为一个映射 import Dat

我有三个函数(
getRow
getColumn
getBlock
),它们有两个参数(x和y),每个参数都生成相同类型的列表。我想写第四个函数来连接它们的输出:

outputList :: Int -> Int -> [Maybe Int]
outputList x y = concat . map ($ y) $ map ($ x) [getRow,getColumn,getBlock]
该函数可以工作,但是有没有办法将双映射(带有三个“$”的)重写为一个映射

import Data.Monoid

outputList :: Int -> Int -> [Maybe Int]
outputList = mconcat [getRow, getColumn, getBlock]

你应该得到一个解释

首先,我要明确指出,所有这些函数都具有相同的类型

outputList, getRow, getColumn, getBlock :: Int -> Int -> [Maybe Int]
现在让我们从你最初的定义开始

outputList x y = concat . map ($ y) $ map ($ x) [getRow,getColumn,getBlock]
这些函数产生一个
[可能是Int]
,任何东西的列表都是一个幺半群。单向组合列表与串联列表相同,因此我们可以将
concat
替换为
mconcat

outputList x y = mconcat . map ($ y) $ map ($ x) [getRow,getColumn,getBlock]
另一个是幺半群的东西是函数,如果它的结果是幺半群的话。也就是说,如果
b
是幺半群,那么
a->b
也是幺半群。单向组合函数与调用具有相同参数的函数,然后单向组合结果相同

所以我们可以简化为

outputList x = mconcat $ map ($ x) [getRow,getColumn,getBlock]
然后再去

outputList = mconcat [getRow,getColumn,getBlock]
我们完了



虽然在本例中,我不确定它是否增加了。

作为第一步,我们观察到您的定义

outputList x y = concat . map ($ y) $ map ($ x) [getRow,getColumn,getBlock]
可以使用函数组合运算符
()
而不是函数应用程序运算符
($)
重写,如下所示

outputList x y = (concat . map ($ y) . map ($ x)) [getRow,getColumn,getBlock]
接下来我们注意到
map
是列表中
fmap
的另一个名称,并且满足
fmap
定律,因此,我们特别有
map(f.g)==map f。地图g
。我们应用这条定律,使用
map
的单个应用程序定义一个版本

outputList x y = (concat . map (($ y) . ($ x))) [getRow,getColumn,getBlock]
outputList x y = concatMap (($ y) . ($ x)) [getRow,getColumn,getBlock]
最后一步,我们可以用
concatMap
替换
concat
map
的组合

outputList x y = (concat . map (($ y) . ($ x))) [getRow,getColumn,getBlock]
outputList x y = concatMap (($ y) . ($ x)) [getRow,getColumn,getBlock]
最后,在我看来,虽然Haskell程序员倾向于使用许多奇特的运算符,但通过

 outputList x y = concatMap (\f -> f x y) [getRow,getColumn,getBlock]

正如它清楚地表达的,函数的作用是什么。但是,使用类型类抽象(如另一个答案中所示)可能是一件好事,因为您可能会发现您的问题具有某种抽象结构并获得新的见解。

我将使用@dave4420的答案,因为它最简洁,并且准确地表达了您的意思。但是,如果您不想依赖
Data.Monoid
,那么您可以按如下方式重写

原始代码:

outputList x y = concat . map ($ y) $ map ($ x) [getRow,getColumn,getBlock]
融合两张地图:

outputList x y = concat . map (($y) . ($x)) [getRow,getColumn,getBlock]
更换
concat。地图
混凝土地图

outputList x y = concatMap (($y) . ($x)) [getRow,getColumn,getBlock]
你完成了


编辑:AAAA,这与@Jan Christiansen的答案完全相同。哦,好吧

顺便问一下,关于Haskell的一个问题需要多长时间才能得到回答,有没有什么统计数据?我的印象是,90%的哈斯克尔问题几乎都能立即得到回答。虽然这并不能说明答案的质量,但在我看来,答案的质量也相当高。@Jancristiansen:如果您愿意,可以使用stack exchange数据资源管理器来回答这个问题。我做了一个非常粗略的近似(过滤明显的异常值,忽略自我答案,&c.),典型的(即中值)时间大约是20分钟,直到发布第一个答案。