简体   繁体   English

haskell:制作Num的超类

[英]haskell : making a superclass of Num

I want to make a superclass of Num, called Linear 我想创建一个名为Linear的Num超类

class Linear a where 
  add :: a -> a -> a

instance (Num a) => Linear a where
  add = (+)

I get the error : 我收到错误:

Illegal instance declaration for `Linear a'
  (All instance types must be of the form (T a1 ... an)
   where a1 ... an are *distinct type variables*,
   and each type variable appears at most once in the instance head.
   Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Linear a'

From what I understand, something about the line instance (Num a) => Linear a where is incorrect. 根据我的理解,有关线条instance (Num a) => Linear a where不正确。 (It compiles if I use the flags : -XFlexibleInstances -XUndecidableInstances ) (如果我使用标志,它会编译: -XFlexibleInstances -XUndecidableInstances

Is there a way to achieve this without using those scary flags? 有没有办法在不使用那些可怕的旗帜的情况下实现这一目标? (and what in the world is undecidable about the code above??) (以及世界上对上述代码不可判断的内容??)

UPDATE : Added Polynomial type to Linear. 更新 :将多项式类型添加到线性。

newtype Polynomial a = Polynomial (a,[a]) deriving Show-- list of coeffients 

instance (Linear a) => Linear (Polynomial a)
         where 
           add (Polynomial (c1, l1)) (Polynomial (c2, l2))
             = Polynomial (add c1 c2, zipWith (add) l1 l2)

p1 = Polynomial (0, [3,4,5])
p2 = Polynomial (0, [])

main = putStrLn $ show ((add p1 p2):: Polynomial Int)

After adding polynomial, it doesn't compile with even those flags and give the error: 添加多项式后,它甚至不会使用这些标志进行编译并给出错误:

Overlapping instances for Linear (Polynomial Int)
  arising from a use of `add'
Matching instances:
  instance Num a => Linear a -- Defined at Algebra.hs:22:10-28
  instance Linear a => Linear (Polynomial a)
    -- Defined at Algebra.hs:25:10-44
In the first argument of `show', namely
  `((add p1 p2) :: Polynomial Int)'
In the second argument of `($)', namely
  `show ((add p1 p2) :: Polynomial Int)'
In the expression: putStrLn $ show ((add p1 p2) :: Polynomial Int)

The language report doesn't allow instances of the form instance Class a where... , so the only way to avoid FlexibleInstances (which is not scary in the least) would be to use a newtype wrapper, 语言报告不允许表单instance Class a where... ,因此避免FlexibleInstances (至少不可怕)的唯一方法是使用newtype包装器,

newtype LinearType a = Linear a

liftLin2 :: (a -> b -> c) -> LinearType a -> LinearType b -> LinearType c
liftLin2 op (Linear x) (Linear y) = Linear (op x y)

instance Num a => Linear (LinearType a) where
    add = liftLin2 (+)

Yuck. 呸。

The UndecidableInstances extension is needed because the constraint Num a is not smaller than the instance head (it uses the same type variables the same number of times), so the compiler can't prove in advance that type checking will terminate. 需要UndecidableInstances扩展,因为约束Num a不小于实例头(它使用相同类型的相同类型的变量),因此编译器无法提前证明类型检查将终止。 Thus you have to promise to the compiler that type checking will terminate for it to accept the programme (it won't actually loop with GHC, that has a context stack that controls recursion-depth of the type checker, so if type checking doesn't finish soon enough, it will fail the compilation with "context stack exceeded" - you can set the size with -fcontext-stack=N ). 因此,您必须向编译器承诺,类型检查将终止它以接受程序(它实际上不会与GHC循环,它具有控制类型检查器的递归深度的上下文堆栈,因此如果类型检查没有'很快完成,它将无法编译“超出上下文堆栈” - 您可以使用-fcontext-stack=N设置大小。

This extension sounds much scarier than it is. 这个扩展听起来比它更可怕。 Basically all it does is tell the compiler "Trust me, type checking will terminate" so the compiler will start without knowing for sure that it will finish. 基本上它所做的只是告诉编译器“信任我,类型检查将终止”,因此编译器将在不确定它将完成的情况下启动。

But, what are you trying to achieve? 但是,你想要实现什么目标? What you currently have, 你现在有什么,

instance (Num a) => Linear a where
  add = (+)

says "every type is an instance of Linear, and if you try to use add at a type not an instance of Num, that is a compile-time error". 说“每个类型都是Linear的一个实例,如果你尝试在类型中使用add而不是Num的实例,那就是编译时错误”。 It's not very useful. 它不是很有用。 You cannot add further instances for types not belonging to Num , unless you enable also OverlappingInstances and possibly IncoherentInstances . 您不能为不属于Num类型添加更多实例,除非您还启用了OverlappingInstances和可能的IncoherentInstances And those extensions are scary, they should be used scarcely and only when you know what you're doing. 这些扩展可怕的,它们应该几乎不用,只有当你知道自己在做什么时。

There is a proposal to allow the declaration of superclasses. 有一个允许声明超类的提议 AFAIK it's not implemented yet, but as GHC is open source, you may change that if you want ;) AFAIK尚未实现,但由于GHC是开源的,如果你愿意,可以改变它;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM