假設我想寫兩個型別類。標題:
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.Complex
第一個型別類 ExClass 定義如下:
class (forall a. (Monoid (t a))) => ExClass t where
exFunc :: [t (Complex a)] -> t (Complex a)
exFunc = mconcat -- the actual function is more complicated
exFunc2 :: (RealFloat a) => t (Complex a) -> a
我將它定義為更高級的型別類,因為它的一個函式的輸出型別取決于其嵌套值的型別a。我也想有一個默認的實作exFunc,但它涉及到t a一個 Monoid的假設。現在我想為以下型別撰寫一個實體:
newtype ExType a = ExType a
ExType a僅當Num a為真時才是Monoid :
instance (Num a) => Semigroup (ExType a) where
ExType a <> ExType b = ExType (a * b)
instance (Num a) => Monoid (ExType a) where
mempty = ExType 1
現在我繼續為 定義型別類實體ExClass,指定約束Num a:
instance (forall a. Num a) => ExClass ExType where
exFunc2 (ExType a) = magnitude a
上面的代碼編譯沒有問題。但是,如果我嘗試像這樣使用已實作的函式:
x = ExType 2 :: ExType (Complex Double)
func = exFunc2 x
我收到以下投訴:
? No instance for (Num a) arising from a use of ‘exFunc2’
Possible fix: add (Num a) to the context of a quantified context
? In the expression: exFunc2 x
In an equation for ‘func’: func = exFunc2 x
當我使用不同的實體宣告時也會發生這種情況:
instance (forall a. Monoid(ExType a)) => ExClass ExType where
exFunc2 (ExType a) = magnitude a
Is there a way to make this typeclass work? or am I just not supposed to structure my program like this at all?
uj5u.com熱心網友回復:
Daniel Wagner 已經在他的回答中解釋了當前定義的問題。
似乎您想表達ExClass的意思是“一類容器型別與c應用于其元素的另一個類具有特殊關系,并且當它們的元素滿足 時c,容器本身就是幺半群”。
例如:ExType與 有特殊關系Num。當元件a的ExType滿足Num,ExType a成為一個Monoid。
(這在ExTypesMonoid實體中已經得到確認,但似乎您想用更高的抽象級別來表達它;為那些以類似方式成為幺半群的容器創建一個類。)
在 Haskell 中,有多種可能的方式來表達兩種型別之間的關系——或者一個型別和一個Constraint. 讓我們使用MultiParameterTypeClasses:
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ConstraintKinds #-}
import Data.Kind (Type, Constraint)
-- This kind signature is not strictly required, but makes things clearer
type ExClass :: (Type -> Constraint) -> (Type -> Type) -> Constraint
class (forall a . c a => Monoid (t a)) => ExClass c t | t -> c where
exFunc :: c a => [t a] -> t a
exFunc = mconcat
請注意,ExClass現在有兩個引數,并且f容器的型別(通過函式依賴)決定c了ffor元素所需的約束為fa Monoid。c對于不同的fs可能會有所不同!
的Semigroup和Monoid實體ExType不變。現在的ExClass實體ExType是:
instance ExClass Num ExType where
exFunc = mconcat
讓它作業:
main :: IO ()
main = print $ exFunc [ExType (1::Int), ExType 2]
(我遺漏了Complex資料型別,這可能會在定義中引發另一個問題。)
uj5u.com熱心網友回復:
我認為這里同時發生了幾個推理錯誤。
第一:當你寫
class (forall a. Monoid (t a)) => ExClass t
這意味著,如果有人想實作的ExClass t情況下,那么他們必須表明,有形式的一個實體instance Monoid (t a) where ...與沒有任何限制的a。還請注意,對于所有可能的選擇存在實體是不夠的a——實體本身必須是引數化的。
第二:當你寫
instance (forall a. Num a) => ExClass ExType
a這里a提到的和定義中提到的之間沒有神奇的聯系ExClass。
第三:寫的時候
instance (forall a. Num a) => ExClass ExType
這實際上還沒有創建一個實體ExClass ExType。它使實體以證明 為條件forall a. Num a。一般來說, 的意思instance Ctx => C t是任何想假設事實的人C t必須能夠自己證明Ctx。沒有人能夠合理地顯示forall a. Num a,所以這個實體是不可用的。
最后兩條評論基本不變地適用于您的第二次嘗試,
instance (forall a. Monoid(ExType a)) => ExClass ExType
不幸的是,如果沒有關于您要做什么以及為什么要做的更多詳細資訊,則幾乎不可能建議正確的前進路線。可能性包括類似索引 monad 的方法,將類約束從類背景關系移動到各種方法背景關系,根本不創建類等等。
uj5u.com熱心網友回復:
我也想有一個默認實作
exFunc,但它涉及的假設t a是Monoid
你只需要Monoid (t a)一個默認的實作?那是倒退。如果該約束在概念上不需要作為 的超約束ExClass,那么它不應該在類頭中。
您仍然可以使用更嚴格的默認實作:
{-# LANGUAGE DefaultSignatures #-}
class ExClass t where
exFunc :: [t (Complex a)] -> t (Complex a)
default exFunc :: Monoid (t (Complex a)) => [t (Complex a)] -> t (Complex a)
exFunc = mconcat
exFunc = mconcat -- the actual function is more complicated
exFunc2 :: (RealFloat a) => t (Complex a) -> a
然后簡單地
instance ExClass ExType where
exFunc2 (ExType a) = magnitude a
您仍然可以提供根本不滿足Monoid約束的實體,然后您也需要手動實作exFunc。
更簡單的是根本不理會默認實作,而只是提供一個幫助程式,可用于獲得簡單的實作,而無需復制任何代碼:
class ExClass t where
exFunc :: [t (Complex a)] -> t (Complex a)
exFunc = mconcat -- the actual function is more complicated
exFunc2 :: (RealFloat a) => t (Complex a) -> a
monoidIshExFunc :: Monoid (t (Complex a)) => [t (Complex a)] -> t (Complex a)
monoidIshExFunc = mconcat
instance ExClass ExType where
exFunc = monoidIshExFunc
exFunc2 (ExType a) = magnitude a
(monoidIshExFunc甚至可以 require ExClass t,很明顯你應該小心不要以回圈定義結束!)
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/316813.html
