为什么(。)地图具有此类型?

时间:2018-07-20 06:57:24

标签: haskell types

我试图找到函数(.) map的类型,但是以某种方式发现它是((a -> d) -> (a -> e)) -> ([d] -> [e]),根据GHCI,它是不正确的,因为它应该是(.) map :: (a1 -> a2 -> b) -> a1 -> [a2] -> [b]

我在做什么错了?

3 个答案:

答案 0 :(得分:6)

派生类型...

我们有成分:

:w

(这里我为两个函数使用了不同的类型标识符,以避免造成任何混淆)。更为冗长的形式(在此我们更明确地指出每个函数都精确地使用一个一个参数):

(.) :: (b -> c) -> (a -> b) -> a -> c
map :: (d -> e) -> [d] -> [e]

由于(.) :: (b -> c) -> ((a -> b) -> (a -> c)) map :: (d -> e) -> ([d] -> [e]) map的第一个参数,这意味着其类型(.)应该与(d -> e) -> ([d] -> [e])函数的输入类型匹配(所以(.)) 。因此,这意味着:

b -> c

所以这意味着 b -> c ~ (d -> e) -> ([d] -> [e]) ------------------------------ b ~ (d -> e), c ~ ([d] -> [e]) 的结果类型是:

(.) map

等效于:

(a -> b) -> (a -> c)

或更简单:

(a -> (d -> e)) -> (a -> ([d] -> [e]))

...及其实现

(.) map :: (a -> d -> e) -> a -> [d] -> [e] 函数可以看成(.)。这意味着我们的功能

(.) f g == \x -> f (g x)

等效于:

h = (.) map

因此,它将函数h f x = map (f x) 和对象f作为输入,然后执行以x为函数的map

从语义上讲,您可以说我们制作了一个{<1>}类型的“ 映射,其中必须插入一个'contect'-objecct ”。然后,处理器会考虑此上下文。如果我们要应用多个f x,每个都有很小的变化,并因此首先传递“上下文对象”,则这可能很有用。当然,这是对人类的一种解释。对于编译器,a可以有任何用途,解释等。

答案 1 :(得分:4)

您可能已经尝试通过查看定义来匹配功能

Types of the two functions
(.) :: ((b -> c) -> (a -> b) -> a -> c)
map :: (d -> e) -> [d] -> [e]

,然后尝试将dbec进行匹配。这样可以给您((a -> d) -> (a -> e)) -> ([d] -> [e]),现在您可以将[d]a进行匹配,并将[e]d进行匹配。但是,这是不正确的,因为根据map的类型定义,ed可以是不同的类型,即d可以是[e]的类型但这不是必须的。

查找此函数类型的正确方法是查看类型的定义

Types of the two functions
(.) :: ((b -> c) -> (a -> b) -> a -> c)
map :: (d -> e) -> [d] -> [e]

,然后将(d -> e)匹配到b,将[d] -> [e]匹配到c,这将为您提供(a -> (d -> e)) -> a -> ([d] -> [e]),方法是删除多余的括号并重命名类型变量得到(a -> b -> c) -> a -> [b] -> [c]。这就是GHCI给您的结果。

答案 2 :(得分:3)

当我不理解函数的类型时,我会使用不同的字母来写类型:

(.) :: (b -> c) -> (a -> b) -> a -> c
map :: (x -> y) -> [x] -> [y]

现在我们提供map作为(.)的第一个参数,因此我们可以得出:

b -> c == (x -> y) -> [x] -> [y] -- by matching first arguments we get...
b == x -> y                      
c == [x] -> [y]

由于我们已经提供了(.)的第一个参数,所以整个b -> c部分都消失了。

(.) map :: (a -> b) -> a -> c                -- Using the above equations for b and c
(.) map :: (a -> x -> y) -> a -> [x] -> [y]  -- changing variables names
(.) map :: (a1 -> a2 -> b) -> a1 -> [a2] -> [b]

GHCi情节