为什么(Num a,Ord a)=>一个

时间:2017-02-21 11:14:46

标签: haskell

我有以下类型签名:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void add(..){..}

当我询问结果类型时:

let kessel :: (Ord a, Num b) => a -> b -> a; kessel = undefined 

我有:

:t kessel 1 2

为什么不kessel 1 2 :: (Num a, Ord a) => a

1 个答案:

答案 0 :(得分:9)

因为1的类型为Num a => a

ghci> :t 1
1 :: Num a => a
ghci> :t kessel
kessel :: (Num b, Ord a) => a -> b -> a
ghci> :t kessel 1
kessel 1 :: (Num a, Num b, Ord a) => b -> a
ghci> :t kessel 1 2
kessel 1 2 :: (Num a, Ord a) => a

来自1Num)的约束将添加添加到已存在的。例如,使用id时,情况相同:

id   :: a -> a
id 1 :: Num a => a

更长的解释

当您使用kessel :: (Ord a, Num b) => a -> (b -> a)时,您告诉编译器kessel任何 a,即Ord的实例。然后,kessel将从任何其他(不一定是不同的)类型b返回一个函数,该函数也是前面提到的类型{Num的一个实例。 1}}。

这意味着您用于a的第一个参数将设置kessel

a

在所有这些情况下,论证的类型都很清楚。但是,如果我们使用多态的值呢?例如这一个:

ghci> :t kessel (1 :: Int)
kessel (1 :: Int) :: Num b => b -> Int
ghci> :t kessel 'A'
kessel 'A' :: Num b => b -> Char
ghci> :t kessel "Hello, World!"
kessel "Hello, World!" :: Num b => b -> String

并让我们使用更简单的功能,即magic :: Magic a => a

const

什么是const :: a -> b -> a const x y = x ?让我们开始更简单。什么是const magic

const "Hello, World?"

我们用const :: a -> b -> a "Hello, World?" :: String const "Hello, World?" :: b -> String 类型替换了 a的每个出现。现在回到我们的"Hello, World?"示例:

magic

同样,我们会将const :: a -> b -> a magic :: Magic t => t const magic :: Magic t => b -> t 的每一个匹配项替换为我们的类型,在本例中为a。但是,我们不能忘记对t的额外限制,即t。我们必须把它带来。因此,我们在这里获得了额外的约束。但如果对Magic有任何限制,我们仍需将其置于a

现在让我们回到原来的t

kessel

我们保留kessel :: (Num b, Ord a ) => a -> b -> a 1 :: (Num n ) => n kessel 1 :: (Num na, Ord na, Num b) => b -> na 的原始约束。因此,我们现在有两个约束,aNum。如果我们现在使用任何满足Ord约束的类型,我们剩下的就是Num。由于它不再在右侧,因此可以放弃其约束:

na