使用具有“有限”约束的约束种类和类型族

时间:2013-01-04 13:27:11

标签: haskell type-families constraint-kinds

我正在使用一个包含monoid的应用程序仿函数来查看"执行。然而,有时候我根本不关心这个部分,所以monoid的选择是无关紧要的,因为它永远不会被消耗掉。我简化了我的所作所为:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}

import GHC.Exts

class Render a b where render :: a -> b
instance Render a () where render = const ()

class Merge a where
  type Renderer a b :: Constraint
  merge :: Renderer a b => a -> b

data Foo = Foo Bool

instance Merge Foo where
  type (Renderer Foo) m = (Render Bool m)
  merge (Foo b) = render b

Render用于将各种a转换为单个bMerge是我实际仿函数的一个很大的简化,但关键是它包含一个类型族/约束,我的目的是准确指定Render Merge所需要的Merge。< / p>

现在,我可能希望&#34;运行&#34; runFoo :: Merge a => a -> Int runFoo x = case merge x of () -> 5 ,但丢弃视图,类似于:

(Renderer a ())

但这会失败,因为:

  

无法推断使用merge

引起的()

我选择a作为我的幺半群,因为forall Render a (),我们有一个Merge a的实例。因此,如果有一种方法可以说Render仅仅意味着集合Merge a约束,那么这将工作正常。当然,runFoo比这更通用 - 它可以添加任意约束,这解释了编译错误。

无论如何要实现我想要的而不用更改{{1}}的签名?

1 个答案:

答案 0 :(得分:6)

如果您有很多这种情况,这可能无法扩展,但这可行:

class Renderer a () => Merge a where
  ...