6

今天我在玩拥抱,遇到了一个非常简单的问题:

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

那会是什么类型?我很难读到这个。

如果它有类型,为什么?我猜这个表达式1 1格式不正确,因此类型检查失败,这是 Haskell 编译器支持的。

4

2 回答 2

12

不,它不是格式错误的。该类型很奇怪,可能没有任何有意义的值,但它仍然是允许的。

请记住,文字是重载的。1不是整数。这是任何类型的东西Num。函数排除在外。没有规则说a -> t 不能是“数字”(即 的实例Num)。

例如,您可以有如下instance声明:

instance Num a => Num (a -> b) where
    fromInteger x = undefined
    [...]

现在1 1简直是平等undefined的。不是很有用,但仍然有效。

可以Num对for 函数进行有用的定义。例如,来自wiki

instance Num b => Num (a -> b) where
     negate      = fmap negate
      (+)         = liftA2 (+)
      (*)         = liftA2 (*)
      fromInteger = pure . fromInteger
      abs         = fmap abs
      signum      = fmap signum

有了这个,您可以编写如下内容:

f + g

wherefgare 函数返回数字。

使用上面的实例声明1 2将等于1. 基本上,用作上述实例的函数的文字等于const <that-literal>.

于 2015-10-13T12:17:07.900 回答
5

在 Haskell 中,1没有固定的类型。它是“任何数字类型”。更准确地说,任何实现Num该类的类型。

特别是,函数类型作为Num. 没有人会这样做,但从技术上讲这是可能的。

所以编译器假设第一个 1是某种数字函数类型,然后第二个 1是任何其他数字类型(可能是相同的类型,也可能是不同的类型)。如果我们将表达式更改为3 6,那么编译器会假设

3 :: Num (x -> y) => x -> y
6 :: Num x => x
3 6 :: (Num (x -> y), Num x) => y
于 2015-10-13T12:15:35.100 回答