计算Haskell函数的类型

Ali*_*liN 3 haskell types functional-programming

在周末的Haskell手动计算给定功能的类型时遇到麻烦.

我理解基础知识,例如:

  • ix = x :: t - > t
  • kxy = x :: t - > t1 - > t

但是在更复杂的问题上遇到麻烦,例如:

  • 两个fx = f(fx)
  • sxyz = xz(yz)

任何解释将不胜感激!

J. *_*son 8

在这两个示例中,您对函数类型的唯一提示来自观察正在进行的应用程序.在Haskell应用程序中几乎没有任何语法,所以我会更明显地重写它们.

two f x = f(f(x))
s x y z = x(z)(y(z))
Run Code Online (Sandbox Code Playgroud)

我们现在将通过逐步细化来发现这些功能的类型.例如,从two我们开始知道它接受两个参数,因此必须具有与(更一般)类型一致的类型

two :: a -> b -> c
Run Code Online (Sandbox Code Playgroud)

我们也知道a上面的类型变量实际上对应于一个函数,因为f它被应用于xf(x).

two :: (a -> b) -> c -> d
Run Code Online (Sandbox Code Playgroud)

由于f到应用x,我们知道,在这里ac必须相同.

two :: (a -> b) -> a -> d
Run Code Online (Sandbox Code Playgroud)

因为我们f再次应用它的结果,f(x)我们知道结果类型必须与输入类型相同

two :: (a -> a) -> a -> b
Run Code Online (Sandbox Code Playgroud)

最后,调用的结果f是总结果,two因此d也必须等于a

two :: (a -> a) -> a -> a
Run Code Online (Sandbox Code Playgroud)

这使用了我们在定义中的所有信息,并且是与定义兼容的最通用类型two.


我们基本上可以做同样的过程s.我们知道它有3个参数

s :: a -> b -> c -> d
Run Code Online (Sandbox Code Playgroud)

我们知道第一个和第二个参数是某种函数.我们看到第二个参数应用于单个值,第一个参数应用于两个值.

s :: (a -> b -> c) -> (d -> e) -> f -> g
Run Code Online (Sandbox Code Playgroud)

我们也知道两个函数的第一个输入是相同的(即,z每次都是).这让我们推断a,df属于同一类型

s :: (a -> b -> c) -> (a -> d) -> a -> e
Run Code Online (Sandbox Code Playgroud)

我们也知道,拨打第二函数的结果是第二个参数的第一个功能,所以bd必须相同.

s :: (a -> b -> c) -> (a -> b) -> a -> e
Run Code Online (Sandbox Code Playgroud)

最后,要充分应用的第一功能的结果是最终结果s,以便ce是相同的

s :: (a -> b -> c) -> (a -> b) -> a -> c
Run Code Online (Sandbox Code Playgroud)

虽然这可能需要消化很多并且有点模糊,但需要强调的是,我用来解决这个问题的工具都是原始的.实际上,(->)当我看到类型应用于某些值时,我会引入箭头,因此必须是一定数量的参数的函数,并且我通过它们的表达式遵循值来统一类型变量.这些是用于推断像two和等简单函数类型的足够工具s.