繁体   English   中英

haskell:制作Num的超类

[英]haskell : making a superclass of Num

我想创建一个名为Linear的Num超类

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

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

我收到错误:

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'

根据我的理解,有关线条instance (Num a) => Linear a where不正确。 (如果我使用标志,它会编译: -XFlexibleInstances -XUndecidableInstances

有没有办法在不使用那些可怕的旗帜的情况下实现这一目标? (以及世界上对上述代码不可判断的内容??)

更新 :将多项式类型添加到线性。

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)

添加多项式后,它甚至不会使用这些标志进行编译并给出错误:

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)

语言报告不允许表单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 (+)

呸。

需要UndecidableInstances扩展,因为约束Num a不小于实例头(它使用相同类型的相同类型的变量),因此编译器无法提前证明类型检查将终止。 因此,您必须向编译器承诺,类型检查将终止它以接受程序(它实际上不会与GHC循环,它具有控制类型检查器的递归深度的上下文堆栈,因此如果类型检查没有'很快完成,它将无法编译“超出上下文堆栈” - 您可以使用-fcontext-stack=N设置大小。

这个扩展听起来比它更可怕。 基本上它所做的只是告诉编译器“信任我,类型检查将终止”,因此编译器将在不确定它将完成的情况下启动。

但是,你想要实现什么目标? 你现在有什么,

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

说“每个类型都是Linear的一个实例,如果你尝试在类型中使用add而不是Num的实例,那就是编译时错误”。 它不是很有用。 您不能为不属于Num类型添加更多实例,除非您还启用了OverlappingInstances和可能的IncoherentInstances 这些扩展可怕的,它们应该几乎不用,只有当你知道自己在做什么时。

有一个允许声明超类的提议 AFAIK尚未实现,但由于GHC是开源的,如果你愿意,可以改变它;)

暂无
暂无

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

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