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

och*_*les 5 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
Run Code Online (Sandbox Code Playgroud)

Render用于将各种as转换为单个b.Merge是我的实际仿函数的一个很大的简化,但关键是它包含一个类型族/约束,我的意图是准确指定所需的Renderers Merge.

现在,我可能想"运行" Merge,但丢弃视图,类似于:

runFoo :: Merge a => a -> Int
runFoo x = case merge x of () -> 5
Run Code Online (Sandbox Code Playgroud)

但这会失败,因为:

无法推断(Renderer a ())使用merge

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

反正有没有改变签名实现我想要的东西runFoo

Sjo*_*her 6

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

class Renderer a () => Merge a where
  ...
Run Code Online (Sandbox Code Playgroud)