代码之家  ›  专栏  ›  技术社区  ›  Todd O'Bryan

在Haskell中,有没有一种方法可以定义一个包含一堆类型约束的类型构造函数?

  •  0
  • Todd O'Bryan  · 技术社区  · 2 年前

    我有一大堆关于两个类型变量的数据类型和函数,它们要求类型 Eq , Ord Show .我发现自己在写作

    type Foo n t = (Eq n, Eq t, Ord n, Ord t, Show n, Show t) => Bar n t -- and
    data Baz n t where
      Baz :: (Eq n, Eq t, Ord n, Ord t, Show n, Show t) => {
        f1 :: !n,
        f2 :: !t
      } -> Baz n t
    

    到处都是。

    有没有办法写这样的东西

    type EqOrdShow d n t = (Eq n, Eq t, Ord n, Ord t, Show n, Show t) => d n t
    

    这样我就可以写作了

    type Foo n t = EqOrdShow Foo n t -- and
    data Baz n t where
      Baz :: {f1 :: !n, f2 :: !t} -> EqOrdShow Baz n t
    

    或者以其他方式为约束列表命名以避免重复?

    1 回复  |  直到 2 年前
        1
  •  3
  •   chi    2 年前

    可以定义约束的别名:

    type EqOrdShow n t = (Eq n, Eq t, Ord n, Ord t, Show n, Show t)
    
    data Baz n t where
      Baz :: EqOrdShow n t => {f1 :: !n, f2 :: !t} -> Baz n t
    

    我认为你无法避免写作 -> Baz something something 显式地位于每个构造函数的类型末尾。


    还要记住,这里的记录字段没有那么有用。例如,以下内容不起作用

    foo :: Baz n t -> String
    foo x = show (f1 x)
    -- No instance for (Show n) arising from a use of `show'
    

    因为只有模式匹配才能带来 Show n 范围中的约束。你需要使用类似的东西

    foo2 :: Baz n t -> String
    foo2 Baz{f1=y} = show y