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

时间:2011-06-29 16:31:30

标签: class haskell types

Hello 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)

导致

Type constructor `Val' used as a class In the definition
of data constructor `Leaf' In the data type declaration for `ExprTree'

我也试过

data ExprTree' = Leaf {lab::Label, val::Val}
         ...

但随机改变的类型签名 - 听起来既不高效也不提供启发。

现在据我所知Num a表示类Num,但这不是数据类型的实例 - 并且不允许我编译。 那么我需要做些什么才能使ExprTree得到很好的定义。

提前感谢提示和想法!


修改

1)感谢快速回答!

2)我将val::(Val a)=>a更改为val::Val a

我有类似的想法 - 然后出现错误:Not in scope type variable a 你有其他建议吗?

5 个答案:

答案 0 :(得分: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)

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

答案 1 :(得分: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)

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

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

* 这不太正确;你需要一种类型*。种类是类型的类型:Int具有种类*Val a具有种类*Val具有种类* -> *。也就是说,Val本身就是类型函数,它需要一个参数才能成为完整类型。

答案 2 :(得分:2)

错误指向类型定义的这一部分:

val::(Val a)=> a

此语法表示“对于类型类a的任何实例Valval的值为a类型。”但是(1)Val不是类型类,(2)类型a似乎是凭空而来的。

您可能打算说的是

data Val a = Num a | Var String
           deriving (Eq, Ord, Show)
data ExprTree a = Leaf { val :: Val a }
                | Node { lBranch :: ExprTree a, rBranch :: ExprTree a }
                deriving (Eq, Ord)

答案 3 :(得分:1)

你的问题已经解决了,但我看到你使用GHC,有时候 - 特别是在开头 - 拥抱错误消息可能更容易阅读,在这种情况下:

  

数据类型声明中的语法错误(意外的`=>')

这实际上可能让你第一个想到在哪里看。请注意,我不是在这里提倡拥抱GHC,但作为Haskell的初学者,我认为前者提供了更多有用的错误信息。

答案 4 :(得分:0)

如果你来自OOP语言,一些简单的规则可能会帮助你获得导向:

  1. 当Haskellers谈论类或类型类时,它隐约地类似于OOP语言中的接口或特征。
  2. 数据的LHS上出现的...... = ......隐约地像一个抽象的超类。你实际上不能制作一个,但你可以声明该类型的参数。
  3. RHS上出现的数据...... = ......与特定的子类模糊不清。
  4. 当您需要一个类型类的参数时,它会在LHS =>>上,如Num t =>吨。
  5. 现在,这些都不是严格正确的,如果你停在这里,但粗略的想法确实帮助我站稳脚跟。