class - haskell make(a类)其他类的实例'

标签 class haskell types

再次Haskellers & Haskellettes,

我仍然有问题,我真的不知道何时使用 (Class a) => aTypeType a,其中 Type 是“联合类型”,例如 ValExprTree

现在我想通过添加一些实例来使我的数据类型 ExprTree 更加通用:

import Ratio
data Fun = Add|Sub|Mul|Div|Pow
    deriving (Eq,Ord)
instance Show Fun where
    show Add = "+"
    show Sub = "-"
    show Mul = "*"
    show Div = "/"
    show Pow = "^"
type Label = Rational
type Var = String
class Eval e where
eval :: (Num a) => e -> a -> a
data ExprTree a = Leaf {lab::Label, val::Val a}
          | Node {lab::Label, fun::Fun, lBranch::ExprTree a, rBranch::ExprTree a}
          deriving(Eq,Ord)
data Val a = Num a | Var String deriving (Eq, Ord, Show)

instance (Num a) => Num (ExprTree a) where
    ...
    fromInteger i = Leaf (0%1) i -- <--error

instance Show (ExprTree a) where
    show (Leaf l a) = show a -- <-- error
    show (Node l f lb rb) = (show lb)++"  "++(show l)
                      ++(show f)++"  "++(show rb)++"\n"

instance Eval (Val a) where
    eval (Var v) n = n
    eval a _ = a -- <-- error

我认为这些问题都是同一类。在一个非常琐碎的环境中不理解类和类型之间的区别等等 - 是我的 Haskell 编程基础上的一个漏洞;所以我真的很想理解这一点,而不是为了解决任何作业。

注意:标签是有理数 - 这使得插入和搜索比使用自然数或整数进行标签更容易。

提前致谢!

最佳答案

您的 fromInteger 的问题是 i 需要转换为 Val a

instance Num a => Num (ExprTree a) where
    -- ...
    fromInteger i = Leaf (0%1) (Val (fromInteger i))

Val 包装器使其成为 Val;内部 fromInteger 创建一个 a,它是调用者指定的类型,我们知道可以使用 fromInteger 创建它,因为 Integer中计算一个约束)。请密切注意最后一点:这是类型类背后的原因。 Num a => 约束确保,给定一个 a,我们知道可以在其上使用任何 Num 实例方法。

另一个问题是同样的问题:您正在调用 show,但您没有采取任何措施来确保 show 上有意义>a.

instance Show a => ExprTree a where
    show (Leaf _ a) = show a -- this works now because we told it a is show-able
    -- ...

Eval 的问题略有不同:a 只是在没有任何源的情况下出现,因此编译器对此一无所知。特别是,eval a _ = a 要求 e 是有效的 a,但 a 是未知的,所以编译器正确地说“什么?”。对于这一点,你需要思考你真正想要做什么;最简单的解决方案是删除 e 并在各处使用 a,但这真的是您想要的吗?

关于class - haskell make(a类)其他类的实例',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6526017/

相关文章:

java - hadoop 使用类名提交作业,为什么需要 job.setJarByClass()?

c++ - 首先在 g++ 中从类到命名空间定义

c - 在 Windows 上为 Haskell 构建 GD 库时出现 ld 错误

types - 为什么 Rust 不能推断 Iterator::sum 的结果类型?

go - 如何更正 "if"构造中的类型比较

ios - 通过其任何 UI 元素(例如按钮、标签、文本字段)仅获取父类的名称

java - 如何创建类的对象 - 但哪个类有所不同,并且取决于其他变量

haskell - 在有序二叉树遍历期间避免列表连接

.net - Haskell 在 F# 中的 "deriving Show"?

C++ 二维数组不显示