Haskell中不同类型之间的关系
Posted
技术标签:
【中文标题】Haskell中不同类型之间的关系【英文标题】:Relation Between the Different Types in Haskell 【发布时间】:2018-10-31 23:46:44 【问题描述】:据我了解,Haskell 有 4 种“类型”:
代数数据类型data
data
类型中的 =
之后的内容;技术上不是类型,我不认为)type
键入别名
带有class
的类型类
使用instance
键入实例
问题是:
-
如果 Haskell 中有更多种类的类型。如果有,有什么关系。
data
类型和class
类型类之间有什么区别。它们看起来很相似,但显然它们有一些不同的特征。与 (3) 相同。
data
类型和 instance
类型类实例之间有什么区别。
我是 Haskell 的新手。
【问题讨论】:
数据类型构造函数不是类型。它是一个“值”,因此比类型低一级。 与class
和instance
相同。我认为有点遗憾的是,Haskell 的命名法与大多数命令式编程语言非常相似,但实际上有一些非常不同的含义。
【参考方案1】:
data
和 newtype
引入了新类型(或实际上是类型构造函数 - Maybe
不是类型,但 Maybe a
是任何 a
的类型)。
data
声明引入了新类型(=
的左侧)和表示该类型数据的方法(=
的右侧)。
例如,如果您有这样的数据声明:
data SomeType = SomeConstructor
然后你引入了一个名为SomeType
的新类型,以及一种构造SomeType
值的方法,即构造函数SomeConstructor
(顺便说一句,它没有任何参数,所以唯一的值包含在这个类型)。
类型类不做这些事情任何一个(instance
也不做)。一个类型类引入了一个 约束 和一堆多态函数,如果满足该约束,这些函数应该可用。 instance
基本上是通过为这些函数提供实现来表示“这种类型符合这个约束”。所以class
并不是真正引入新类型,它只是为现有类型提供临时多态性的一种方式。
例如,Show
类型类大致是这样的:
class Show a where -- a is an instance of Show if
show :: a -> String -- it has a function called show with this signature
(请注意,Prelude
中的实际 Show
类并不很看起来像这样)
show
现在具有 Show a => a -> String
类型,您可以将其解读为
对于所有 a,如果它们满足约束
Show
(或者,如果它们是Show
的实例),这是一个接受a
并返回字符串的函数
这样的一个实例看起来像这样
instance Show SomeType where
show SomeConstructor = "SomeConstructor"
这意味着
SomeType
满足约束Show
,我将通过提供show
的实现来向您展示如何实现
这大概就是它的要点。有一些语言扩展允许类型类和实例发生更多涉及的事情,但您现在不必担心。
【讨论】:
在带有ConstraintKinds
的 GHC Haskell 中,类型类确实以某种方式引入了新类型,不是针对普通类型(类型为 *
)而是针对约束; class Num a where … ; class Functor f where …
创建类型构造函数 Num :: * -> Constraint
和 Functor :: (* -> *) -> Constraint
。约束仍然是类型,只是没有值。【参考方案2】:
您可能听说过 kinds,它们是 Haskell 中的“类型的类型”。类型是一种类型为*
的东西,它表示可以有值的东西:
> :kind Int
Int :: *
> :kind Char
Char :: *
类型构造函数是类型为* -> *
的东西;类型构造函数接受一个类型(*
之类的东西)并返回另一种类型。
> :kind Maybe
Maybe :: * -> *
> :kind []
[] :: * -> *
应用类型构造函数为您提供了一种新事物*
:
> :kind Maybe Int
Maybe Int :: *
> :kind [] Float
[] Float :: *
(解析器允许[Foo]
作为[] Foo
的特例。)
还有其他种类的东西。其中之一是Constraint
,您可以使用约束构造函数(也称为类型类)创建Constraint
。给一个约束构造函数一个类型,你就会得到一个约束。
> :kind Show
Show :: * -> Constraint
> :kind Show Int
Show Int :: Constraint
> :kind Show (Int -> Char)
Show (Int -> Char) :: Constraint
(请注意,即使没有定义 Int -> Char
的实例,后者也是正确的。)
从这个角度来看,=>
看起来像一个运算符,而不仅仅是特殊的语法。它的参数是一个约束的“列表”(尽管使用普遍量化的类型变量而不是具体类型)和一个类型,它的返回值是一个“约束”类型(假设除了@987654336 之外还有一种ConstrainedType
@、* -> *
和 Constraint
)。
:t show
show :: Show a => a -> String
-- Taking extreme liberties with syntax
-- :k (=>)
-- (=>) :: [Constraint] -> * -> ConstrainedType
-- A section?
-- :k (Show a =>)
-- (Show a =>) :: * -> ConstrainedType
-- :k (Showa => * -> String)
-- Show a => a -> String :: ConstrainedType
【讨论】:
以上是关于Haskell中不同类型之间的关系的主要内容,如果未能解决你的问题,请参考以下文章
Haskell:在 ByteStrings 和不同的文本编码之间进行转换
如何使用haskell类型系统来描述关系,从而防止出现更多错误
Rust闭包和Haskell lambda有什么区别? [关闭]
如何在 Javascript 中实现 Haskell 的 FRP Behavior 类型?