[英]Explicit forall on a type class function
從ghc-8.0開始,我們有一個非常好的擴展名為TypeApplications
。 這允許我們而不是:
λ> show (5 :: Int)
"5"
這樣做是這樣的:
λ> :set -XTypeApplications
λ> show @Int 5
"5"
這真的很酷。 當我們添加更多類型變量時,它會變得更加復雜,但是有一些規則可以用來確定確切的順序,並且它們有很好的記錄:
showFooBar :: (Show a, Show b) => a -> b -> String
showFooBar a b = show a ++ " and " ++ show b
所以在上面的函數中我們首先提供a
然后b
:
λ> showFooBar @Int @Double 3 4
"3 and 4.0"
這很好,但是如果我想改變訂單怎么辦? 沒問題,我們可以使用ExplicitForAll
擴展(或其他一些暗示它)來指定它:
{-# LANGUAGE ExplicitForAll #-}
showFooBar :: forall b a . (Show a, Show b) => a -> b -> String
showFooBar a b = show a ++ " and " ++ show b
現在我們顛倒了我們要應用的類型順序:
λ> showFooBar @Int @Double 3 4
"3.0 and 4"
問題是我似乎無法弄清楚如何為屬於類型類的函數實現相同的效果。 考慮這個例子:
{-# LANGUAGE MultiParamTypeClasses #-}
class (Show a, Show b) => FooBar a b where
fooBarClassFunc :: a -> b -> String
我現在不能把forall
放在一個函數上(例如fooBarClassFunc :: forall ab . a -> b -> ..
,因為它改變了函數的含義,顯然不能編譯。
那么,問題是,在類型類方法中,如何為TypeApplication
更改類型變量的順序?
編輯
為了以防萬一,我已經嘗試過InstanceSigs
擴展,並且就TypeApplications
而言它完全忽略了forall
類型變量的順序,這是一件好事,否則我們最終會得到由實例決定的行為,而不是類。
在類型類方法中,如何為
TypeApplication
更改類型變量的順序?
我想,@ luqui的答案已經足夠好了。 但為什么不這樣:
class (Show b, Show a) => FooBar b a where
fooBarClassFunc :: a -> b -> String
您只有一個方法,因此驅動類的參數順序的唯一考慮因素是方法中的TypeApplication
。
如果有兩個或更多的方法您想要的順序TypeApplication
是不同的(@志的觀點,但為什么呢?),然后換另一方法或者luqui的建議,或(等效)的其他類與父約束和默認實現。
class (Show a, Show b, FooBar b a) => OtherFooBar a b where
otherFooBarClassFunc :: a -> b -> String
otherFooBarClassFunc = otherFooBarClassFunc' -- default
instance {-# NOOVERLAPPABLE #-} OtherFooBar a b where {} -- take default
(假設在主類中定義了otherFooBarClassFunc'
;那就是真實實例定義所在的位置。)
當然, 每個班級有一個方法可以說很多。
{-# NOOVERLAPPABLE #-}
我們不是'ave'是我的小玩笑。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.