[英]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.