Haskell 类型和签名

Haskell types and signatures

我正在备考 Haskell。我不明白如何确定函数的类型。函数为:

func [] f = 16
func (h : t) f = (f h) + (func t f)

我的猜测是第一行具有以下类型:empty list -> a -> a 其中 a 必须是数字类型。在 Haskell 表示法 Num a => [] -> a -> a 中,第二行有这样的类型: [a]-> a -> ? 它是什么 return?也许 (a, a) 因为 (f h) 是一个元组。 (func t f)呢,是a还是?以及如何将两条线混合在一起?

func [] f = 16

这一行定义了一个函数 func,接受列表和 f,以及 returning 16。类型可以写成 Num a => [b] -> c -> a.

func (h : t) f = (f h) + (func t f)

此行将 f 类型限制为 Num a => b -> a,因为:

  1. f 应该接受列表中的一个元素
  2. f ... 应该 return 一个值,可以将其添加到 func ...
  3. 的结果中

所以,func的类型是:

Num a => [b] -> (b -> a) -> a

找出此类问题的一种(简单)方法是将其写入文件并将其加载到 ghci 并发出命令 :t func,这在准备考试时非常有用但在此期间不适用 - 所以我将引导您完成可以找到的提示。

由于@soon 给出了一个完全有效的答案 - 我只会添加一些您将来可能会用到的提示:

确定参数的个数(如果函数是以pointfree风格写的,这可能有点困难,即func x = const x可以写成func = const.

所以在这种情况下我们得到两个参数和一个结果所以我们可以将签名写成

func :: ? -> ? -> ?
  1. 查找结果(在本例中为 16)并确定其类型 您已经注意到 16 是数字 - 因此

    func :: Num a => ? -> ? -> a
    

    看起来是个不错的起点。

  2. 寻找可以帮助您识别函数中的 ADT 或 type/newtype 的类型构造函数。

    现在在第一种和第二种情况下,我们有两个提示,即第一个参数是列表类型([] 和构造函数 (:))给了我们这个信息。由于我们没有关于列表内容的信息,我们必须为它们分配一个不同类型的变量 - b.

    func :: Num a => [b] -> ? -> a
    
  3. 确定用于确定其余部分的函数或为您已经发现的内容获取更专业的类型

    这里我们有 2 个信息,一个是 (+) 运算符,(f h) - 因为 haskell 中的空白字符表示我们得到 h 的函数应用程序必须是函数 f 的域,并且 f h 的结果与 (+) :: Num a => a -> a -> a 一起使用(请注意,两个参数必须具有相同的类型,以及结果)和func t f(即 a)的结果我们得到 f 的目标类型,因此 f :: b -> a

合成这个我们得到

func :: Num a => [b] -> (type-of-f) -> a
func :: Num a => [b] -> (b -> a) -> a