Haskell 什么';参数多态性和高级类型之间的区别是什么?
我敢肯定他们不一样。然而,我陷入了困境 “锈不支持”更高种类类型(HKT)的常见概念,但 而是提供参数多态性。我试着让我的头绕过去,理解它们之间的区别,但是越来越纠结 据我所知,锈有更高级的种类,至少是最基本的种类。使用“*”符号,HKT确实有一种类型,例如Haskell 什么';参数多态性和高级类型之间的区别是什么?,haskell,rust,higher-kinded-types,type-theory,parametric-polymorphism,Haskell,Rust,Higher Kinded Types,Type Theory,Parametric Polymorphism,我敢肯定他们不一样。然而,我陷入了困境 “锈不支持”更高种类类型(HKT)的常见概念,但 而是提供参数多态性。我试着让我的头绕过去,理解它们之间的区别,但是越来越纠结 据我所知,锈有更高级的种类,至少是最基本的种类。使用“*”符号,HKT确实有一种类型,例如*->*。 例如,可能属于*->*类型,可以在Haskell中这样实现 数据可能a=只是a |什么都没有 这里, 可能是一个类型构造函数,需要应用于具体类型 成为“*”类的具体类型 只有一个和没有是数据构造函数 在关于哈斯克尔的教科书中
*->*
。
例如,可能属于*->*
类型,可以在Haskell中这样实现
数据可能a=只是a |什么都没有
这里,
可能是一个类型构造函数,需要应用于具体类型
成为“*”类的具体类型
只有一个
和没有
是数据构造函数
在关于哈斯克尔的教科书中,这经常被用作一种更高级类型的例子。但是,在Rust中,它可以简单地实现为枚举,毕竟它是一种总和类型:
再说一次,在哈斯凯尔,这大概是
do_something :: Maybe a -> ()
do_something :: Maybe a -> ()
do_something _ = ()
这就引出了第四个问题
对更高级类型的支持到底在哪里结束?有什么问题
使Rust的类型系统无法表示HKT的最小示例
相关问题:
我浏览了很多与主题相关的问题(包括他们与博客帖子的链接等),但我找不到我的主要问题(1和2)的答案
更新
谢谢你提供了很多很好的答案,这些答案都非常详细,帮助很大。我决定接受安德烈亚斯·罗斯伯格的回答,因为他的解释最有助于我走上正轨。特别是术语部分
我真的陷入了这样一个循环:所有的东西*->*…->*代码>是更高级的。强调*->*->*
和(*->*)->*
之间区别的解释对我来说至关重要。我将继续说明:更高种类的类型只是类型级别的高阶函数
但请花一分钟:
考虑monad
变压器:
newtype StateT s m a :: * -> (* -> *) -> * -> *
这里,
什么是高级类型
m :: (* -> *)
因为接受一种类型*
,并返回一种类型*
它就像一个类型上的函数,也就是一个类型构造函数
* -> *
在像Java这样的语言中,你不能这样做
class ClassExample<T, a> {
T<a> function()
}
class类示例{
T函数()
}
在Haskell中,T将具有种类*->*
,但Java类型(即类)不能具有该种类的类型参数,即更高种类的类型
另外,如果您不知道,在basic Haskell中,表达式的类型必须是kind*
,即“具体类型”。任何其他类型,如*->*
例如,您不能创建类型为的表达式,可能是。它必须是应用于参数的类型,比如可能是Int
,可能是String
,等等。换句话说,是完全应用的类型构造函数。Rust不能做的一个简单示例是Haskell的Functor
类
类函子f,其中
fmap::(a->b)->f a->f b
--举几个例子:
实例函子可能在哪里
--fmap::(a->b)->可能a->可能b
fmap uuo无=无
fmap f(正好x)=正好(fx)
实例函子[],其中
--fmap::(a->b)->[a]->[b]
fmap[]=[]
fmap f(x:xs)=fx:fmap fxs
请注意,实例是在类型构造函数上定义的,可能
或[]
,而不是完全应用的类型可能是a
或[a]
这不仅仅是一个客厅的把戏。它与参数多态性有很强的交互作用。由于类型fmap
中的类型变量a
和b
不受类定义的约束,因此Functor
的实例无法基于它们更改其行为。在从类型推理代码时,这是一个非常强大的属性,Haskell的类型系统的强大之处就在于此
它还有一个特性——您可以编写抽象类型更高的类型变量的代码。这里有几个例子:
focusFirst::函子f=>(a->fb)->(a,c)->f(b,c)
聚焦第一f(a,c)=fmap(\x->(x,c))(f a)
聚焦秒::函子f=>(a->FB)->(c,a)->f(c,b)
聚焦秒f(c,a)=fmap(\x->(c,x))(f a)
我承认,这些类型开始看起来像抽象的废话。但当你有几个助手利用了更高级的抽象时,它们就变得非常实用了
newtype Identity a=Identity{runIdentity::a}
实例函子标识,其中
--fmap::(a->b)->身份a->身份b
fmap f(身份x)=身份(身份x)
newtype Const c b=Const{getConst::c}
实例函子(常量c),其中
--fmap::(a->b)->常数c a->常数c b
fmap u(常数c)=常数c
设置::((a->Identity b)->s->Identity t)->b->s->t
设置f b s=runIdentity(f(\\->Identity b)s)
获取::((a->Const a b)->s->Const a t)->s->a
get fs=getConst(f(\x->Const x)s)
(如果我在那里犯了错误,有人能帮我修复吗?我正在从内存中重新实现lens
的最基本起点,而无需编译器。)
函数focusFirst
和focusSecond
可以作为第一个参数传递给get
或set
,因为它们类型中的类型变量f
可以与get
和set
中更具体的类型统一。能够抽象更高级类型的变量f
允许特定形状的函数在
m :: (* -> *)
* -> *
class ClassExample<T, a> {
T<a> function()
}