Haskell:如何使用具有泛型数据类型的类型类?

时间:2017-06-26 07:39:10

标签: haskell generics typeclass

假设我已经定义了这样的列表:

data List a = Nil | Cons a (List a)

现在我想确保List仅使用符合特定类型类(例如Ord)的泛型类型进行实例化。我怎么能这样做?

我知道可以在泛型函数上定义类型类约束,该函数将与List个实例一起使用,但有没有办法在数据类型本身上定义这样的约束?

1 个答案:

答案 0 :(得分:4)

GADT可以在构造函数中捕获约束的字典。

{-# LANGUAGE GADTs #-}

data Sortable a where
    Sortable :: Ord a => [a] -> Sortable a
--     ^          ^
--  constructor   |
--                |
--  captures an Ord dictionary

在构造函数模式匹配时重新引入字典

sortSortable :: Sortable a -> Sortable a
sortSortable (Sortable xs) = Sortable (sort xs)
--               ^                     ^
-- match constructor                   |
--                                     |
-- reintroduces `Ord a` dictionary so it can be used in sort
Sortable a具有a实例

时,可以构建

Ord a

{-# LANGUAGE StandaloneDeriving #-}

deriving instance Show a => Show (Sortable a)

main = print . sortSortable $ Sortable "Hello, world!"

但不是在它没有

的时候
data Z = Z
  deriving (Show)

main = print . sortSortable $ Sortable [Z]

这会导致错误,因为Sortable无法捕获Ord Z字典,因为一个字典不存在。

No instance for (Ord Z) arising from a use of ‘Sortable’
In the second argument of ‘($)’, namely ‘Sortable [Z]’
In the expression: print . sortSortable $ Sortable [Z]
In an equation for ‘main’:
    main = print . sortSortable $ Sortable [Z]