gpt4 book ai didi

haskell : making a superclass of Num

转载 作者:行者123 更新时间:2023-12-02 10:06:41 26 4
gpt4 key购买 nike

我想创建一个 Num 的父类(super class),称为 Linear

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 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 不小于实例头(它使用相同类型变量相同次数),因此编译器无法提前证明类型检查将终止。因此,您必须向编译器 promise 类型检查将终止,以便它接受程序(它实际上不会使用 GHC 循环,GHC 有一个控制类型检查器递归深度的上下文堆栈,因此如果类型检查不进行)如果完成得不够快,编译将会失败,并显示“上下文堆栈超出” - 您可以使用 -fcontext-stack=N 设置大小。

这个扩展听起来比实际要可怕得多。基本上它所做的就是告诉编译器“相信我,类型检查将终止”,因此编译器将在不知道它是否会完成的情况下启动。

但是,您想要实现什么目标?您目前拥有的,

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

表示“每种类型都是 Linear 的实例,如果您尝试在不是 Num 实例的类型上使用 add ,则会出现编译时错误”。这不是很有用。您无法为不属于 Num 的类型添加更多实例,除非您还启用 OverlappingInstances 以及可能的 IncoherentInstances。这些扩展很可怕,应该很少使用它们,并且只有当您知道自己在做什么时才应该使用它们。

关于 haskell : making a superclass of Num,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9870962/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com