我在學習GHC仿製藥。在回顧了幾個例子之後,我想嘗試創建一個通用的Functor
實例(不管GHC能爲我自動推導它們)。然而,我意識到我不知道如何使用泛型的參數化數據類型,我見過的所有例子都是*
。這是可能的,如果是的話,如何? (我對SYB等其他類似框架也很感興趣。)如何使用GHC.Generics(或其他類似的框架)構造泛型函子實例?
9
A
回答
8
使用GHC Generics查找大量示例函數的最佳位置是generic-deriving
package。那裏有一個Functor
類的通用定義。複製從Generics.Deriving.Functor
(略簡體):
class GFunctor' f where
gmap' :: (a -> b) -> f a -> f b
instance GFunctor' U1 where
gmap' _ U1 = U1
instance GFunctor' Par1 where
gmap' f (Par1 a) = Par1 (f a)
instance GFunctor' (K1 i c) where
gmap' _ (K1 a) = K1 a
instance (GFunctor f) => GFunctor' (Rec1 f) where
gmap' f (Rec1 a) = Rec1 (gmap f a)
instance (GFunctor' f) => GFunctor' (M1 i c f) where
gmap' f (M1 a) = M1 (gmap' f a)
instance (GFunctor' f, GFunctor' g) => GFunctor' (f :+: g) where
gmap' f (L1 a) = L1 (gmap' f a)
gmap' f (R1 a) = R1 (gmap' f a)
instance (GFunctor' f, GFunctor' g) => GFunctor' (f :*: g) where
gmap' f (a :*: b) = gmap' f a :*: gmap' f b
instance (GFunctor f, GFunctor' g) => GFunctor' (f :.: g) where
gmap' f (Comp1 x) = Comp1 (gmap (gmap' f) x)
class GFunctor f where
gmap :: (a -> b) -> f a -> f b
default gmap :: (Generic1 f, GFunctor' (Rep1 f))
=> (a -> b) -> f a -> f b
gmap = gmapdefault
gmapdefault :: (Generic1 f, GFunctor' (Rep1 f))
=> (a -> b) -> f a -> f b
gmapdefault f = to1 . gmap' f . from1
要在數據類型利用這一點,你必須得到Generic1
而非Generic
。 Generic1
表示法的關鍵區別在於它使用編碼參數位置的Par1
數據類型。
3
* -> *
類型的數據類型有Generic1
類。使用它的方式與*
類型的數據類型大致相同,但參數的Par1
也是如此。例如,我用它在我的unfoldable package中。
相關問題
- 1. 如何調用類的構造泛型類型的構造
- 2. 如何在JavaScript中使用構造函數返回實例或其他?
- 3. Scala:使用私有構造函數從泛型類型創建實例
- 4. 如何使用實體框架核心的泛型類型?
- 5. 在C#中使用泛型創建類似類型的實例
- 6. 我如何使用泛型類的構造函數
- 7. 使用泛型類型的參數化構造函數基類
- 8. 我應該在構造函數中實例化其他類嗎?
- 9. 實體框架的泛型類型
- 10. Java - 擴展似乎是調用其他類的構造函數
- 11. 構造一個泛型Java類,其中T是foo類或foo的子類
- 12. 如何實例化其構造函數使用yield的對象?
- 13. 如何使用約束構造Applicative實例(類似於使用ContT構造Monad實例)
- 14. 具有非泛型構造函數的泛型F#類型
- 15. 使用泛型類型的Java構造函數
- 16. 使用實體框架和ADO.NET模型的泛型類型
- 17. 從泛型類泛型類中缺少構造函數
- 18. 構造泛型類型
- 19. Java:子類構造函數的super()如何參與實例流?
- 20. 泛型類型的靜態構造函數如何工作?
- 21. 如何在其他構造函數中調用構造函數?
- 22. 重載構造函數根據輸入類型調用其他構造函數
- 23. 是否支持非泛型類中的泛型構造函數?
- 24. VB.NET - 如何在泛型類型的實例上調用實例函數委託?
- 25. 泛型和類,在構造函數中決定子類
- 26. 使用構造函數自動裝配泛型類型[Spring 4.2.5]
- 27. 使用實體框架4使用ContextBuilder與泛型類創建EDMX/DB架構的例外
- 28. 使用enumset的泛型類的構造函數的問題
- 29. C#泛型 - 類實現其他泛型類
- 30. 使用實體框架生成實體的構造函數
GHC是否會自動導出'Generic1'的實例? –
@PetrPudlák不完全自動。但是通過'DeriveGeneric'語言擴展,你可以使用'派生Generic'以及'派生Generic1'(後者只適用於至少有一個參數的數據類型,最後一個參數類型爲'*')。 – kosmikus
@kosmikus謝謝。不幸的是,對於我的目標,我希望能夠處理更復雜的類型,所以我可能不得不使用Template Haskell。 –