function - 两个相似的函数如何在 Haskell 中具有不同的多态类型?

标签 function haskell types polymorphism fibonacci

我对 Haskell 很陌生,所以如果我遗漏了关键概念,请指出。

假设我们有这两个函数:

fact n
     | n == 0 = 1
     | n > 0  = n * (fact (n - 1))
fact 的多态类型是 (Eq t, Num t) => t -> t 因为 n 用于 if 条件,并且 n 必须是有效类型才能进行 == 检查。因此 t 必须是 Number 并且 t 可以是类约束 Eq t 内的任何类型

fib n
    | n == 1 = 1
    | n == 2 = 1
    | n > 2  = fib (n - 1) + fib (n - 2)

那为什么 fib 的多态类型是 (Eq a, Num a, Num t) => a -> t 呢?

看不懂,求帮助。

最佳答案

Haskell 始终致力于导出最通用的类​​型签名。

现在对于 fact ,我们知道输出的类型应该与输入的类型相同:

fact n | n == 0 = 1
       | n > 0  = n * (fact (n - 1))

这是由于最后一行。我们使用 n * (fact (n-1)) 。所以我们使用乘法 (*) :: a -> a -> a 。因此乘法需要两个相同类型的成员并返回该类型的一个成员。由于我们与 n 相乘,并且 n 是输入,因此输出与输入的类型相同。由于我们使用 n == 0 ,我们知道 (==) :: Eq a => a -> a -> Bool 意味着该输入类型应该有 Eq a => ,而且还有 0 :: Num a => a 。所以结果类型是 fact :: (Num a, Eq a) => a -> a

现在对于 fib ,我们看到:
fib n | n == 1 = 1
      | n == 2 = 1
      | n > 2  = fib (n - 1) + fib (n - 2)

现在我们知道对于 n ,类型约束又是 Eq a, Num a ,因为我们使用 n == 1(==) :: Eq a => a -> a -> Bool1 :: Num a => a 。但是 输入 n 从不直接用于输出 。事实上,最后一行有 fib (n-1) + fib (n-2) ,但在这里 我们使用 n-1n-2 作为新调用 的输入。所以这意味着我们可以安全地假设输入类型和输出类型是独立的。输出类型,仍然有一个类型约束: Num t :这是因为我们在前两种情况下返回 11 :: Num t => t ,我们还返回两个输出的相加: fib (n-1) + fib (n-2) ,所以再次 (+) :: Num t => t -> t -> t

关于function - 两个相似的函数如何在 Haskell 中具有不同的多态类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45459637/

相关文章:

c# - 在同一方法签名中的函数的 TIn 的扩展方法中使用此类型参数的类型

Java 泛型和泛型类型

c - 将指针交换为 C 中的指针

javascript - 对象的默认函数?

haskell - HXT 跳过错误元素

scala - Scala对 map 进行多分区-类型不匹配;找到(A,B)=>需要 bool 值(A,B)=> bool 值吗?

c - 在函数中修改 vector

java - 如何编写一个程序来提出多项选择问题,然后对每个答案执行输入操作?

java - 做 "not contained in"最简洁的方法?

Haskell IO 递归