首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >函数从“m附录”函数到“`Monoid`”实例?

函数从“m附录”函数到“`Monoid`”实例?
EN

Stack Overflow用户
提问于 2015-02-21 18:49:01
回答 1查看 432关注 0票数 3

我有一个数据结构(它是玫瑰树的一个特定子类,它形成一个具有最大下界和最低上界函数的格),它支持两个完全合理的函数作为Monoid类的mappend

在haskell中有任何方法支持匿名Monoid实例吗?在这种情况下,我应该考虑使用诸如Template-Haskell之类的东西来为我生成类型类吗?

我想要的是一个让我动态创建实例的makeMonoid :: (RT a -> RT a -> RT a) -> Monoid a,但我理解这与我所理解的股票类型系统是不一致的。如果我只需要选择一个默认的合并函数并为其他合并编写newtype,我就没问题了,只是好奇

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-21 22:09:49

您可以动态地创建Monoid的“本地”实例,使用反射包中的工具。存储库中有一个现成的例子。这个答案解释了一点。

这是一个a类型值的新类型包装器,我们将在它上定义我们的Monoid实例。

代码语言:javascript
复制
newtype M a s = M { runM :: a } deriving (Eq,Ord)

注意,有一个幻影类型的s没有出现在右手边。它将携带本地Monoid实例工作所需的额外信息。

这是一个记录,其字段表示Monoid类的两个操作:

代码语言:javascript
复制
data Monoid_ a = Monoid_ { mappend_ :: a -> a -> a, mempty_ :: a }

下面是用于MonoidM实例定义

代码语言:javascript
复制
instance Reifies s (Monoid_ a) => Monoid (M a s) where
    mappend a b        = M $ mappend_ (reflect a) (runM a) (runM b)
    mempty = a where a = M $ mempty_ (reflect a)

它说:“每当s是我们的Monoid字典Monoid_的类型级表示时,我们就可以将它反射回来以获得字典,并使用字段为M实现Monoid操作”。

注意,传递给reflect的实际值reflect没有使用,它只是作为M a s类型的“代理”传递,它告诉reflect要使用哪种类型(s)来“带回记录”。

实际的本地实例是使用reify函数构造的:

代码语言:javascript
复制
withMonoid :: (a -> a -> a) -> a -> (forall s. Reifies s (Monoid_ a) => M a s) -> a
withMonoid f z v = reify (Monoid_ f z) (runM . asProxyOf v)

asProxyOf :: f s -> Proxy s -> f s
asProxyOf a _ = a

asProxyOf函数是一种使编译器相信在单面体中使用的幻影类型与reify提供的Proxy中的幻影类型相同的技巧。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28649854

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档