我在这里使用了Haskell解释器:https://tryhaskell.org/
当我提供输入时,5 1
它告诉我-我假设它是类型-表达式的类型是(Num a, Num (a -> t)) => t
:
λ 5 1
:: (Num a, Num (a -> t)) => t
现在,我试图理解如何解释这一点,这就是我的想法。
a
是任何Num
类型,也是a -> t
。该表达式产生某种类型t
,该类型是从理论上将1
(type a
)应用于5
(type a -> t
)而产生的。
这真的让我感到困扰,因为我不明白约束的Num (a -> t)
意义。从理论上讲,这似乎是正确的解释,但我找不到证明。
这是有道理的,因为它Num
是一个多态类型-可以是一个函数。
在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
依此类推。我敢肯定有人会为此找到一个有趣的用例,但我不建议这样做,这显然不是很直观。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句