在Haskell中(12)是什么类型的?



我今天在玩拥抱的游戏,被一个非常简单的问题卡住了:

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

这个类型是什么?我看不懂这个

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

不,它不是病态的。该类型很奇怪,可能不存在任何有意义的值,但它仍然是允许的。

请记住字面量是重载的。1不是整数。它是任何类型的Num。函数不包括在之外。没有规则说a -> t 不能是"一个数字"(即Num的一个实例)。

例如,你可以有一个instance声明:

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

现在1 1就等于undefined。不是很有用,但仍然有效。

可以为函数定义有用的Num。例如,从wiki

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

你可以这样写:

f + g

其中fg是返回数字的函数。

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

在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

最新更新