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