簡體   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