使用类型族来避免MPTC中的显式类型参数

时间:2014-05-05 14:46:54

标签: haskell type-families

我想知道是否有任何方法(可能使用 Type Families )使用Buildable方法定义build类型类,以便这样的方法可以工作:

>>> import qualified Data.ByteString.Builder as B (Builder)
>>> import qualified Data.Text.Lazy.Builder as T (Builder)

>>> -- This should internally use `int8` from `Data.ByteString.Builder`:
>>> build (8::Int8) :: B.Builder

>>> -- This should internally use `decimal` from `Data.Text.Lazy.Builder`:
>>> build (8::Int8) :: T.Builder

>>> -- If no concrete type is specified, I'd expect something like this:
>>> :t build (8::Int8)
GBuilder Int8

我知道如何使它与MPTC协同工作,但我必须明确定义要构建的值的类型和构建器的类型。有没有办法让类型系统自动选择预期的类型而不明确地传递它?

1 个答案:

答案 0 :(得分:5)

嗯,明显的解决方案如下:

class Builder b where
  type Element b
  build :: Element b -> b

instance Builder B.Builder where
  type Element B.Builder = Int8
  build = B.int8

instance Builder T.Builder where
  type Element T.Builder = Int8
  build = T.decimal

然而,问题在于类型系列不能用于确定实例。因此,在这种情况下,实例只能由b中的build :: Element b -> b确定,而不能由Element b确定。在处理类型检查错误时,这很有用。

由于我在很多情况下刚刚提到的内容,因此只能使用数据系列。标准方法是提供newtype包装器。 E.g:

class Builder b where
  data Element b
  build :: Element b -> b

instance Builder B.Builder where
  newtype Element B.Builder = BElement Int8
  build (BElement a) = B.int8 a

在这种情况下,可以从b的{​​{1}}和Element b确定实例。