簡體   English   中英

類型類函數的顯式forall

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM