理解`5 1'的类型

时间:2015-03-27 02:22:48

标签: haskell types

我在这里使用了这个Haskell解释器:https://tryhaskell.org/

当我提供输入5 1时,它告诉我 - 我认为它是类型 - 表达式是(Num a, Num (a -> t)) => t类型:

λ 5 1
:: (Num a, Num (a -> t)) => t

现在我试图理解如何解释这一点,这就是我想出来的。

aNum类型,a -> t也是t类型。表达式导致某些类型1通过理论上将a(类型5)应用于a -> t(类型Num (a -> t))而生成。

这真让我感到不安,因为我看不出约束Num是如何有意义的。从理论上讲,它看起来是正确的解释,但我无法找到证据。


解释是正确的

这是有道理的,因为{{1}}是一个多态类型 - 它可以是一个函数。

3 个答案:

答案 0 :(得分:9)

数字在Haskell中是多态的。当你写像

这样的东西
5

编译器将其转换为fromInteger (5 :: Integer) :: Num a => a。编译器事先并不知道要使用哪个实例,因此它最好从上下文中猜测。如果你有5 1,那么第一个数字是多态Num类型,它也必须是一个函数。第二个数字只是Num,所以这很正常。

但你可能会问"一个数字怎么能成为一个函数?"如果世界上的一切都有意义,那么数字就不是函数,但你实际上可以为它们编写一个或多或少的实例:

{-# LANGUAGE FlexibleInstances #-}

instance Num a => Num (a -> a) where
    fromInteger a = const (fromInteger a)
    a + b = \c -> a c + b c
    a * b = \c -> a c * b c
    abs a = \c -> abs (a c)
    signum a = \c -> signum (a c)
    negate a = \c -> negate (a c)

这满足了定义,但它可能不是非常有用。例如:

> let x = 1 :: Int -> Int; y = 2 :: Int -> Int
> x + y $ 0
3
> x + y $ 102089
3
> x + y $ undefined
3

所以在这里,论证与表达无关,它甚至没有被评估。如何更有趣的一个:

> let x = (+10); y = (*10)
> x + y $ 0    -- x 0 + y 0 = 0 + 10 + 0 * 10
10
> x + y $ 1    -- x 1 + y 1 = 1 + 10 + 1 * 10
21
> x + y $ 2
32

等等。我确定有人可以找到一个有趣的用例,但我不推荐它,它显然不是很直观。

答案 1 :(得分:2)

在Haskell中,数字是多态的:

λ> :t 5
5 :: Num a => a

重要这里需要注意的是Haskell中的函数应用程序是空白。因此,要制作类似5 2类型检查的内容,您只需为(a -> a)类型创建一个实例。

答案 2 :(得分:1)

您的解释是正确的。

  

我没有看到约束Num(a - > t)是否有意义。

这里的关键是任何事物都可以是Num类型,只要代码中的某个地方有一个实例声明即可。因此,对于某些ataNum类型),您编写了instance Num (a -> t) where ...,那么a -> t将是{ {1}}类型和Num实际上可以评估为值。