今天我一直在玩拥抱,并陷入一个非常简单的问题:
? 1 1
:: (Num a, Num (a -> t)) => t
Run Code Online (Sandbox Code Playgroud)
那种类型是什么?我很难读到这个.
如果它有类型,为什么?我猜测表达式1 1是错误的,因此类型检查失败,Haskell编译器支持.
Bak*_*riu 12
不,它不是不成形的.类型很奇怪,可能没有任何有意义的值,但它仍然是允许的.
请记住,文字是重载的.1是不是一个整数.它是任何类型的东西Num.功能不排除在此之外.没有规则说a -> t 不能是"数字"(即一个实例Num).
例如,你可以有一个instance声明如下:
instance Num a => Num (a -> b) where
fromInteger x = undefined
[...]
Run Code Online (Sandbox Code Playgroud)
现在1 1简直是平等的undefined.不是很有用但仍然有效.
您可以拥有有用的Num函数定义.例如,来自维基
instance Num b => Num (a -> b) where
negate = fmap negate
(+) = liftA2 (+)
(*) = liftA2 (*)
fromInteger = pure . fromInteger
abs = fmap abs
signum = fmap signum
Run Code Online (Sandbox Code Playgroud)
有了这个,你可以写下这样的东西:
f + g
Run Code Online (Sandbox Code Playgroud)
where f和gare函数返回数字.
使用上面的实例声明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
Run Code Online (Sandbox Code Playgroud)