考虑以下功能:
f :: a -> Int
f x = (1 :: Int)
我们可能会说f
的类型为a -> Int
,因此f
属于“多态”类型。
以下哪一项是考虑f
的最准确方法?
实际上有一个类型为f
的单 a -> Int
。但是,它可以用作f :: Int -> Int
,f :: Double -> Int
等等。
从字面上讲,f
的类型不是a -> Int
。实际上,这只是一种简短的方式,表示存在函数f
的 family ,其类型是具体的(即,有f :: Int -> Int
,{{1} }等等;此外,这些功能中的每一个都彼此不同。)
同样,我们可以考虑以下类型声明:
f :: Double -> Double
并且问两种观点中的哪一种更正确:
没有单类型data Maybe a = Just a | Nothing
;事实上,只有一系列具体类型(Maybe
,Maybe Int
等),仅此而已。
实际上 是一种类型Maybe String
。这种类型是一种更高级的类型。当我们说它是一个“类型”时,我们的意思是字面意思(不是(1)的简写)。碰巧我们也可以编写Maybe
,Maybe Int
等来生成不同的类型(这恰好是具体的)。但是,在一天结束时(即):Maybe Double
,Maybe
和Maybe Int
表示三个不同的类型,其中两个是具体的,其中一个这是更高的。
在Haskell中,“高级类型”真的有类型吗?或者只是具体类型“真实类型”,当我们谈到“更高级的类型”时,我们只是表示具体类型的家族。此外,paramametrically多态函数表示单一类型的函数,或者它们仅表示具体类型的集合函数(仅此而已)?
答案 0 :(得分:9)
目前还不完全清楚你想要问什么,两种情况下1和2之间的实际区别是什么,但从基础数学的角度来看:
参数多态函数
f
实际上有f :: forall a.a->int
对于Haskell所基于的类型化lambda演算中的函数,它是完全合法的类型。它可以是:
f = λa:Type.λx:a.(body for f)
你如何从中获得Double->Int
?您将应用于Double
类型:
f Double = (λa:Type.λx:a.(body for f)) Double => λx:Double.(body for f|a=Double)
Haskell在场景后面执行两种操作(类型抽象和类型应用程序),尽管可以使用forall
GHC扩展明确声明类型签名中的XExplicitForAll
部分,并明确地生成{{带有类型签名的Double->Int
实例:
f
更高的金币类型
考虑一个简单的类型:
f_double :: Double -> Int
f_double = f
(是的,它是data Example = IntVal Int | NoVal
)。
Maybe Int
是类型构造函数,就像Maybe
是数据构造函数一样。这是完全相同的事情,只有IntVal
应用于Maybe
的意义上只有一个级别更高级别,就像Type
应用于{{1}一样}}
在lambda演算中,IntVal
具有类型:
Int
Haskell不允许您从类型构造函数中获取类型,但允许您获取种(这只是类型的奇特名称>):
Maybe
所以不,Maybe : Type->Type
不是类型:您不能拥有类型为:k Maybe
Maybe :: * -> *
的对象。 Maybe
(几乎)是从类型到类型的函数,例如Maybe
是从值到值的函数。
我们将Maybe
应用于IntVal
的结果称为Maybe
,就像我们将String
应用于Maybe String
作为IntVal
一样}。
答案 1 :(得分:6)
首先提出一个问题:声明"所有列表的长度是否为"单个陈述或一系列陈述" list1有长度"," list2有长度",...?
如果您将f
的类型设为明确forall
,则会获得f :: forall a. a -> Int
。首先,这不是更高级的"。我们可以在GHCI中执行以下操作:
λ> :set -XRankNTypes
λ> :k (forall a. a -> Int)
(forall a. a -> Int) :: *
所以f
有一种*
。
现在,在Haskell中,我们可以使用~
来表示类型相等。我们可以设置以下内容来检查GHCI中的内容:
λ> :set -XImpredicativeTypes
λ> :set -XTypeFamilies
λ> :t undefined :: ((~) Int Int) => a
undefined :: ((~) Int Int) => a :: a
这表明GHC为这个例子找出了类型相等。类型不等式将产生以下错误:
λ> undefined :: ((~) (Int -> Int) (Int)) => a
<interactive>:22:1:
Couldn't match expected type ‘Int’ with actual type ‘Int -> Int’
In the expression: undefined :: ((~) (Int -> Int) (Int)) => a
In an equation for ‘it’:
it = undefined :: ((~) (Int -> Int) (Int)) => a
现在直接使用此方法会阻止我们比较f
的类型,但我发现了一个应该适用于我们目的的轻微变体:
λ> :t undefined :: forall a. ((a -> Int) ~ (Int -> Int)) => a
undefined :: forall a. ((a -> Int) ~ (Int -> Int)) => a :: Int
换句话说,如果f
的类型等效于g :: Int -> Int
,则a
必须为Int。这类似于x = y
,y = 0
所以x = 0
。在我们指定x = 0
之前,我们没有y = 0
,直到那时我们才x = y
。
Maybe
不同,因为它有以下类型:
λ> :k Maybe
Maybe :: * -> *
由于我们正在使用DataKinds
,因此我们有:k (~) :: k -> k -> GHC.Prim.Constraint
,因此我们可以执行以下操作:
λ> :t undefined :: (~) Maybe Maybe => Int
undefined :: (~) Maybe Maybe => Int :: Int
λ> :k Either ()
Either () :: * -> *
λ> :t undefined :: (~) Maybe (Either ()) => Int
Couldn't match expected type ‘Either ()’ with actual type ‘Maybe’
总而言之,f :: forall a. a -> Int
与声明一样有意义,如果你给我任何东西,我会给你一个Int&#34;。你能否把这句话翻译成一堆陈述&#34;如果你给我一只狗......&#34;,&#34;如果你给我一分钱......&#34;?是的,但它削弱了声明。最后,准确地确定你的意思是什么&#34;相同&#34;你得到了答案。