Haskell - 类与类型类 - 有什么区别

eps*_*lbe 8 haskell types class

您好Haskellers和Haskellettes,

我已经花了很长一段时间在Haskell上摆弄,但是有一个我无法理解的类概念.在以下示例中,我的数据类型为ExprTree

data Val a = Num a | Var String deriving (Eq, Ord, Show)
data ExprTree = Leaf {lab::Label, val::(Val a)=> a}
          | Node {lab::Label, fun::Fun, lBranch::ExprTree, rBranch::ExprTree}
          deriving(Eq,Ord)
Run Code Online (Sandbox Code Playgroud)

这导致

Type constructor `Val' used as a class In the definition
of data constructor `Leaf' In the data type declaration for `ExprTree'
Run Code Online (Sandbox Code Playgroud)

我也试过了

data ExprTree' = Leaf {lab::Label, val::Val}
         ...
Run Code Online (Sandbox Code Playgroud)

但随机改变的类型签名 - 既没有效果,也没有提供启示.

现在据我所知,Num a表示类的东西,Num但这不是数据类型的实例 - 并且不让我编译.那么我需要做些什么才能做好ExprTree定义.

提前感谢您的提示和想法!


编辑:

1)感谢快速的答案!

2)I改变val::(Val a)=>aval::Val a

我有类似的东西 - 然后错误:Not in scope type variable a发生你有额外的建议?

sep*_*p2k 5

回答标题中的问题:在讨论Haskell时,"类"这个词几乎总是用来表示"类型类",因为它是Haskell中唯一的类.所以没有区别.

要回答你体内的问题:

data ExprTree a =
    Leaf {lab::Label, val::(Val a)}
    | Node {lab::Label, fun::Fun, lBranch::(ExprTree a), rBranch::(ExprTree a)}
    deriving(Eq,Ord)
Run Code Online (Sandbox Code Playgroud)

写入(Val a)=>a是没有意义的,因为Val它不是类型类,你不能只在类型定义的右侧引入类型类约束(无论如何都没有扩展 - 无论哪种方式都不是你想要的).


gee*_*aur 3

正确的类型是

data Val a = Num a | Var String deriving (Eq, Ord, Show)
data ExprTree a = Leaf {lab::Label, val :: Val a}
          | Node {lab::Label, fun::Fun, lBranch::ExprTree a, rBranch::ExprTree a}
          deriving(Eq,Ord)
Run Code Online (Sandbox Code Playgroud)

由于该类型Val需要一个额外的类型参数,因此每次使用它时都需要提供一个*。我使用了一个类型变量,就像最初的定义一样;这要求变量也被命名为 的参数ExprTree。(其他可能性是使用具体类型,例如IntorMaybe String等​​,或使用存在类型;这两种类型在这里都没有意义。)

您实际使用的是类型类上下文(“类”只是“类型类”的简写)。 Val是一种类型,而不是类型类,因此它在那里不合法。

*这并不完全正确;你需要一种类型*。种类是类型的类型: Inthas kind *Val ahas kind *Valhas kind * -> *。也就是说,它本身Val就是一个类型函数,需要参数才能成为完整类型。

  • 从技术上讲,Val 甚至不是一个*类型*,而是一个*类型**构造函数***,或者一个简单的类型函数。 (2认同)