4

我正在研究一个包含一个用于“查看”执行的幺半群的应​​用函子。然而,有时我根本不关心这部分,所以幺半群的选择是无关紧要的,因为它永远不会被消耗。我已经简化了我所拥有的:

{-# 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用于将各种as 转换为单个b. Merge是我实际仿函数的一个很大的简化,但关键是它包含一个类型族/约束,我的意图是准确指定Renderers a 的Merge要求。

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

runFoo :: Merge a => a -> Int
runFoo x = case merge x of () -> 5

但这会失败,因为:

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

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

有没有在不改变签名的情况下实现我想要的runFoo

4

1 回答 1

5

如果您有很多这样的情况,这可能无法扩展,但这有效:

class Renderer a () => Merge a where
  ...
于 2013-01-04T15:19:44.480 回答