[英]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. 这些扩展是可怕的,它们应该几乎不用,只有当你知道自己在做什么时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.