Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用基于整数Haskell的新类型执行代数_Haskell_Algebra_Newtype - Fatal编程技术网

用基于整数Haskell的新类型执行代数

用基于整数Haskell的新类型执行代数,haskell,algebra,newtype,Haskell,Algebra,Newtype,我在执行简单的加法、减法时遇到了一些麻烦——任何类型的代数都需要Haskell的新类型 我的定义是(包括显示,以便我可以将它们打印到控制台): 我想做的基本上是: Money 15 + Money 5 = Money 20 Money 15 - Money 5 = Money 10 Money 15 / Money 5 = Money 3 等等,但我越来越 m = Money 15 n = Money 5 Main>> m-n ERROR - Cannot infer insta

我在执行简单的加法、减法时遇到了一些麻烦——任何类型的代数都需要Haskell的新类型

我的定义是(包括显示,以便我可以将它们打印到控制台):

我想做的基本上是:

Money 15 + Money 5 = Money 20
Money 15 - Money 5 = Money 10
Money 15 / Money 5 = Money 3
等等,但我越来越

m = Money 15
n = Money 5
Main>> m-n

ERROR - Cannot infer instance
*** Instance   : Num Money
*** Expression : m - n

我找不到一个清晰而周全的解释来解释这里的遗产是如何运作的。非常感谢您提供的任何帮助。

哈斯克尔无法累计两笔钱,因为您从未指定如何累计。为了增加两个
a
s,
a
s应该实现
Num
typeclass。事实上,
newtype
s经常用于指定不同的类型实例,例如,并用于定义两个不同的幺半群

因此,您需要将其作为的实例,因此您必须定义一个实例,如:

instance Num Money where
    Money a + Money b = Money (a+b)
    Money a - Money b = Money (a-b)
    Money a * Money b = Money (a*b)
    abs (Money a) = Money (abs a)
    signum (Money a) = Money (signum a)
    fromInteger = Money
由于是
fractal
typeclass的成员,这将产生一些问题,因为您的
Money
包装了
Integer
对象

但是,您可以实现typeclass,使其支持
div
。为了做到这一点,我们需要实现和类型类。
Real
typeclass要求类型实现,并且由于
Ord
typeclass要求对象是typeclass的实例,因此我们最终实现了
Eq
Ord
Real
Enum
typeclass

instance Eq Money where
    Money x == Money y = x == y

instance Ord Money where
    compare (Money x) (Money y) = compare x y

instance Real Money where
    toRational (Money x) = toRational x

instance Enum Money where
    fromEnum (Money x) = fromEnum x
    toEnum = Money . toEnum

instance Integral Money where
    toInteger (Money x) = x
    quotRem (Money x) (Money y) = (Money q, Money r)
        where (q, r) = quotRem x y
generalizednewtypedering
因为我们可以使用名为的GHC扩展

上面的推导非常“无聊”,我们每次“展开”数据构造函数,执行一些操作,然后“重新包装”它们(在某些情况下,不需要展开或重新包装)。尤其是由于运行时实际上不存在
newtype
(这更像是让Haskell以不同方式对待数据的一种方式,但数据构造函数将“优化掉”),因此没有太大意义

如果我们使用以下工具进行编译:

ghc -XGeneralizedNewtypeDeriving file.hs

Haskell将为我们进行上述推导。据我所知,这是一个GHC功能,因此其他Haskell编译器本身并不支持这一功能。

您缺少一个关于您的钱是如何加在一起的实例,线索是错误的
实例:Num money

因此,对于Haskell中的加法,
Num
键入在处理数字时将两件事情相加所需的内容,因此让我们在
Money
上创建一个
Num
的实例:

newtype Money =
  Money Integer deriving Show

instance Num Money where
  Money a + Money b = Money $ a + b

-- Money 1 + Money 2 == Money 3

请注意,它返回
Money
,将让您研究如何从类型中获取数字:)

没有继承。每个类型都必须自己实现其所有的typeclass实例。Will Ness是对的,不过我要指出的是,GHC通常可以自动为您派生这些实例。只是你需要问一下。。。对于
Num
,目前实际上根本不可能进行派生。比我的答案更深入一些:)可能值得一提
generalizednewtypedering
。)
newtype Money = Money Integer deriving (Show, Num, Enum, Eq, Ord, Real, Integral)
newtype Money =
  Money Integer deriving Show

instance Num Money where
  Money a + Money b = Money $ a + b

-- Money 1 + Money 2 == Money 3