使用基于整数Haskell的新类型执行代数 [英] Performing algebra with newtypes based on integers Haskell

查看:107
本文介绍了使用基于整数Haskell的新类型执行代数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在执行简单的加减运算时遇到了麻烦-真正具有Haskells newtype的任何代数.

I'm having some trouble with performing simple addition, subtraction -- any kind of algebra really with Haskells newtype.

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

My definition is (show included so I can print them to console):

newtype Money = Money Integer deriving Show

我想做的基本上是:

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

对于这里的继承是如何工作的,我找不到清晰简明的解释.任何帮助都将不胜感激.

I can't find a clear and consise explanation as to how the inheritance here works. Any and all help would be greatly appreciated.

推荐答案

Well Haskell不能将两个Money相加,因为您从未指定如何执行此操作.为了加总两个aa应该实现Num类型类.实际上,newtype通常用于指定不同类型的实例,例如

Well Haskell can not add up two Moneys, since you never specified how to do that. In order to add up two as, the as should implement the Num typeclass. In fact newtypes are frequently used to specify different type instances, for example Sum and Product are used to define two different monoids.

因此,您需要使其成为

You thus need to make it an instance of Num, so you have to define an instance like:

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

(/) :: Fractional a => a -> a -> a Fractional类型类的成员,这会带来一些问题,因为您的Money包装了Integer对象.

Since (/) :: Fractional a => a -> a -> a is a member of the Fractional typeclass, this will give some problems, since your Money wraps an Integer object.

不过,您可以实现 类型类,使其支持div.为此,我们需要实现 Enum 类型类. Real类型类要求该类型实现

You can however implement the Integral typeclass such that it supports div. In order to do this, we however need to implement the Real and Enum typeclass. The Real typeclass requires the type to be implement the Ord, and since the Ord typeclass requires the object to be an instance of the Eq typeclass, we thus end up implementing the Eq, Ord, Real and 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

GeneralizedNewtypeDeriving

作为 @Alec说我们可以使用名为 -XGeneralizedNewtypeDeriving .

GeneralizedNewtypeDeriving

As @Alec says we can use a GHC extension named -XGeneralizedNewtypeDeriving.

上面的推导是非常无聊的",这里我们每次解包"数据构造函数,执行一些动作并解包"它们(在某些情况下,不需要解包或重新包装).尤其是由于newtype实际上在运行时不存在(这是让Haskell区别对待数据的一种方法,但是数据构造函数将被优化"),这没有什么意义.

The above derivations are quite "boring" here we each time "unwrap" the data constructor(s), perform some actions, and "rewrap" them (well in some cases either unwrapping or rewrapping are not necessary). Especially since a newtype actually does not exists at runtime (this is more a way to let Haskell treat the data differently, but the data constructor will be "optimized away"), it makes not much sense.

如果我们使用以下代码进行编译:

If we compile with:

ghc -XGeneralizedNewtypeDeriving file.hs

我们可以将Money类型声明为:

we can declare the Money type as:

newtype Money = Money Integer deriving (Show, Num, Enum, Eq, Ord, Real, Integral)

,Haskell将为我们执行以上推导.据我所知,这是GHC功能,因此其他Haskell编译器本身不 (当然,他们当然可以具有此功能)支持该功能.

and Haskell will perform the above derivations for us. This is, to the best of my knowledge, a GHC feature, and thus other Haskell compilers do not per se (well they can of course have this feature) support this.

这篇关于使用基于整数Haskell的新类型执行代数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆