如何使用map创建部分应用函数的列表?

4
我正在尝试制作一个函数列表(稍后与zipwith一起使用),以便我有效地拥有 [take 1,take 2,take 3] ,因此列表的每个元素应具有类型 [Int] -> [Int] 。 这是我尝试过的内容,感觉应该是正确的。 我不确定为什么会收到错误消息?
Prelude> map (\x -> take x) [1..5]

<interactive>:46:1:
    No instance for (Show ([a0] -> [a0]))
      (maybe you haven't applied enough arguments to a function?)
      arising from a use of ‘print’
    In a stmt of an interactive GHCi command: print it

6
错误信息仅表示GHCi不知道如何打印函数列表的结果。表达式本身没有问题。您仍然可以使用:t来请求其类型。这应该可以正常工作。 - kosmikus
1
此外,您还可以通过 eta 减少 lambda:map take [1..5]同样有效。 - phipsgabler
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3
首先,你的代码可以运行。但是函数无法获得show n。尝试使用show id,你最终会得到非常相似的错误消息。 但在深入研究您的功能列表应用之前,让我们先看一下类型,以检查您的逻辑是否正确。为了简单起见,我们说1 :: Int。同时,\x -> take x 可以被简化为take,因此我们可以通过map take [1..5]来重现您的行为。现在我们在小型类型混乱中有以下参与者:
map    :: (a -> b           ) -> [a]    -> [b]
take   :: Int -> ([c] -> [c])                   -- explicit parentheses
现在我们将take插入map。在我们的map中,由于take的第一个参数,a~Int,而b~[c]->[c]。因此,我们有:
map take :: [Int] -> [[c] -> [c]]
现在我们使用map take [1..5],它只是简单地在上一行中删除类型:
map take        :: [Int] -> [[c] -> [c]]
[1..5]          :: [Int]
map take [1..5] ::          [[c] -> [c]]

我们完成了。最终得到的类型与您的错误信息完全相同。一切都结束得很好吗?是的。您的代码没有问题。

然而,正如已经提到的,[[c] -> [c]] 无法显示。我们必须在列表中应用这些函数:

Prelude> map (\f -> f [1..10]) (map take [1..5])
[[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5]]

1

@kosmikus在评论中回答了你的问题,但是如果有人感兴趣,这里是控制台中:t命令的作用。

以下是您要求的5个函数列表,直接输入:

Prelude> :t [(take 1), (take 2), (take 3), (take 4), (take 5)]
[(take 1), (take 2), (take 3), (take 4), (take 5)] :: [[a] -> [a]]
使用您的表达式与map
Prelude> :t map (\x -> take x) [1..5]
map (\x -> take x) [1..5] :: [[a] -> [a]]
顺便提一下,你也可以这样说:

Prelude> :t map take [1..5]
map take [1..5] :: [[a] -> [a]]
你无法在GHCI控制台中显示函数列表的值,也就是说,无法显示从列表到列表的函数。@kosmikus提供的:t技巧很好用。尽管如此,你仍然可以使用你的函数列表并查看它们的运行情况。例如:
Prelude> let takers = map take [1..5] in head(tail takers) [8,9,10,11]
[8,9]
应用函数take 2到列表[8 9 10 11]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,