2017-08-04 73 views
5

我打了一下,用zipWith和接触之后:第二个参数如何成为函数列表?

Prelude Control.Applicative> :t zipWith id 
zipWith id :: [b -> c] -> [b] -> [c] 

为什么编译期待下一个参数的函数列表?

我试图分析,但不能得出结论,为什么下一个参数必须是函数列表。

当我通过idzipWith时,签名是如何得到应用的?

+5

值得关注的是,这是更常见的写作'zipWith($)'。其工作原理完全相同; '''运算符只是一个缩小版本的'id'。 – leftaroundabout

+1

如果你“试图分析”,你应该包括你试图分析的细节,或者潜在的答复者可能只是重新解释你理解的内容,而完全错过你不了解的内容。 – user2407038

回答

14

类型的zipWith是:

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 

id类型是:

id :: d -> d 

所以,如果我们现在要得出的zipWith id类型,我们推的id :: d -> d类型成第一个参数的类型为zipWith

d -> d 
~ a -> (b -> c) 

这意味着:a ~ da ~ b -> c。所以这意味着zipWith id的类型现在是:

zipWith id :: [a] -> [b] -> [c] 
-> zipWith id :: [b -> c] -> [b] -> [c] 

这是如何工作:第一个列表必须包含的功能f :: b -> c列表,第二个列表,元素x :: b的列表,并由此计算元素列表f x :: c

例如:

Prelude> zipWith id [(+1),(5/),(3*),(3-)] [1,4,2,5] 
[2.0,1.25,6.0,-2.0] 

因为1+12.05/41.253*26.03-5-2.0

所以zipWith id将采取两个元素fx,以及对这些应用id f x,或更详细的(id f) x。由于id ff,因此它将计算f x

因此我们可以得出结论,zipWith是一个元素映射。

+0

'〜'是什么意思? –

+1

@zero_coding:表示[*类型相等*](https://stackoverflow.com/a/27667708/67579)。因此,例如'a〜d'意味着'a'和'd'是相同的类型。 [进一步阅读](https://wiki.haskell.org/GHC/Type_families#Equality_constraints)。 –

+0

@zero_coding我已经添加了一个可以让你理解'〜'的答案。只是简单的类型推理逻辑。但是,@Willem Van Onsem的回答非常好。 – pamu

5

谢谢Willem Van Onsem给出了很好的答案。

让我们从ghc的类型推断系统的角度来理解zipWith id

第一,考虑的zipWithzipWith

Prelude> :info zipWith 
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 
    -- Defined in ‘GHC.List’ 

第一自变量的类型是接受一个函数,它接受两个参数的函数。

(a -> b -> c)也可以重新写为a -> (b -> c)

现在考虑zipWith idid的类型是从a -> a

我们已经把id放在一个必须使用两个参数函数的地方。

因此,类型推理将使(a -> b -> c)样子a -> (b -> c)(通知a -> (b -> c)需要一个arument和给b -> c即一个参数的功能。)

但是,使a -> (b -> c)标识功能将是可能的,只有a是( b - > c)。

a是(二 - > c)该函数a -> b -> c变为((二 - > C) - >(B - > C))

所以,类型推断系统将推断a作为(b -> c)并将所得输出将是[a] -> [b] -> [c]替换ab -> c

用(b→c)代替a

使(a - > b - > c)看起来像id。 (a→b→c)可以看起来像id通过上述替换。 ((b→c)→b→c),其中x为(b→c)→b→c),其中(b→c)→b→c) C)

zipWith :: ((b -> c) -> b -> c) -> [b -> c] -> [b] -> [c] 

所以最后我们得到的输出[b -> c] -> [b] -> [c]

相关问题