我想知道是否有任何方法(可能使用 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协同工作,但我必须明确定义要构建的值的类型和构建器的类型。有没有办法让类型系统自动选择预期的类型而不明确地传递它?
答案 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
确定实例。