我正在使用一个包含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
转换为单个b
。 Merge
是我实际仿函数的一个很大的简化,但关键是它包含一个类型族/约束,我的目的是准确指定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}}的签名?
答案 0 :(得分:6)
如果您有很多这种情况,这可能无法扩展,但这可行:
class Renderer a () => Merge a where
...