确定Haskell函数的类型

cb7*_*cb7 3 haskell

过去的考试问题是ring用定义陈述函数的类型ring r q p = r (q p)。答案可能是ring :: (b -> c) -> (a -> b) -> (a -> c),但我不知道这是从哪里来的。这样的类型肯定会指示ring仅接收两个参数,但是在定义中它需要三个参数,所以这是怎么回事?

Wil*_*sem 5

Haskell中的每个函数都有一个参数。但是,函数可以返回带有另一个参数的函数。但是,Haskell引入了一些语法以使其更加方便。(b -> c) -> (a -> b) -> (a -> c)因此,签名等同于(b -> c) -> ((a -> b) -> (a -> c))(b -> c) -> (a -> b) -> a -> c

让我们首先分析一下表达式:

ring r q p = r (q p)
Run Code Online (Sandbox Code Playgroud)

由于目前我们还不太了解类型,因此我们将首先为参数分配一些类型:

r :: a
q :: b
p :: c
ring :: a -> b -> c -> d
Run Code Online (Sandbox Code Playgroud)

现在我们可以开始确定类型。在表达式中,我们看到q p,因此意味着这q是一个函数和p一个参数。因此,这意味着它q是类型的函数c -> e(带有e我们引入的类型参数)。

因此,我们得出:

q :: c -> e
p :: c
q p :: e
Run Code Online (Sandbox Code Playgroud)

接下来,我们看到的结果q p被用作r函数的参数,因此意味着这r是一个采用eas作为参数类型的函数。因此,我们将的类型设置re -> f。因此,我们知道:

q p :: e
r :: e -> f
r (q p) :: f
Run Code Online (Sandbox Code Playgroud)

由于的结果ring r q pr (q p),因此这意味着类型ring为:

ring :: (e -> f) -> (c -> e) -> c -> f
Run Code Online (Sandbox Code Playgroud)

或更详细:

ring :: (e -> f) -> ((c -> e) -> (c -> f))
Run Code Online (Sandbox Code Playgroud)