链接/组合Haskell中的类型类 [英] Linking/Combining Type Classes in Haskell

查看:96
本文介绍了链接/组合Haskell中的类型类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个类型定义如下,它们在功能上是相同的,但名称不同:

  class Monad m where 
(>> =):: ma - > (a - > m b) - > m b
return :: a - > m a

class PhantomMonad p其中
pbind :: p a - > (a - > p b) - > p b
preturn :: a - > pa

有没有办法将这两个类绑定在一起,这样PhantomMonad的一个实例会自动的成为Monad的一个实例,还是每个类的实例都必须被明确写入?任何见解都将非常感谢,谢谢!

解决方案

希望做的不是真的可行。你可以编写一个看起来像你想要的实例,可能需要一些GHC扩展,但它不会按照你喜欢的方式工作。



不明智的答案:您可以使用可怕的类型级元编程完成您想要的任务,但它可能会变得复杂。这真的不建议,除非你绝对需要这个工作出于某种原因。



官方实例不能真正依赖其他实例,因为GHC在做决策时只考虑实例负责人,并且类别约束在背景中。为了使类似于类类同义词在这里,你必须为所有可能的类型编写类似 Monad 的实例,这显然没有意义。您将与 Monad 的其他实例重叠,这有其自身的问题。



,我不认为这样的实例会满足实例解析的终止检查要求,所以您还需要 UndecidableInstances 扩展名,这意味着可以编写实例将发送GHC的类型检查器到一个无限循环。



如果你真的想要去那个兔子洞,浏览 Oleg Kiselyov的网站一点点;他是Haskell中类型级元编程的守护神。



这很有趣,但是如果你只是想编写代码并使其工作,可能不值得痛苦。



编辑:好的,事后我在这里夸大了这个问题。诸如 PhantomMonad 之类的东西可以很好地作为一次性使用,并且应该按照您的要求进行操作,给定重叠 - 和 UndecidableInstances GHC扩展。当你想做任何比问题更复杂的事时,复杂的东西就会启动。我衷心感谢诺曼拉姆齐给我打电话 - 我真的应该知道更好。



我还没有真正推荐做这种事,没有很好的理由,但并不像我声称的那样糟糕。 Mea culpa。

Say I have two type classes defined as follows that are identical in function but different in names:

class Monad m where
    (>>=)  :: m a -> (a -> m b) -> m b
    return :: a -> m a

class PhantomMonad p where
    pbind    :: p a -> (a -> p b) -> p b
    preturn  :: a -> p a

Is there a way to tie these two classes together so something that is an instance of PhantomMonad will automatically be an instance of Monad, or will instances for each class have to be explicitly written? Any insight would be most appreciated, thanks!

解决方案

Good answer: No, what you're hoping to do isn't really viable. You can write an instance that looks like it does what you want, possibly needing some GHC extensions in the process, but it won't work the way you you'd like it to.

Unwise answer: You can probably accomplish what you want using scary type-level metaprogramming, but it may get complicated. This really isn't recommended unless you absolutely need this to work for some reason.

Officially instances can't really depend on other instances, because GHC only looks at the "instance head" when making decisions, and class constraints are in the "context". To make something like a "type class synonym" here, you'd have to write what looks like an instance of Monad for all possible types, which obviously doesn't make sense. You'll be overlapping with other instances of Monad, which has its own problems.

On top of all that, I don't think such an instance will satisfy the termination check requirements for instance resolution, so you'd also need the UndecidableInstances extension, which means the ability to write instances that will send GHC's type checker into an infinite loop.

If you really want to go down that rabbit hole, browse around on Oleg Kiselyov's website a bit; he's sort of the patron saint of type-level metaprogramming in Haskell.

It's fun stuff, to be sure, but if you just want to write code and have it work, probably not worth the pain.

Edit: Okay, in hindsight I've overstated the issue here. Something like PhantomMonad works fine as a one-off and should do what you want, given the Overlapping- and UndecidableInstances GHC extensions. The complicated stuff starts up when you want to do anything much more complicated than what's in the question. My sincere thanks to Norman Ramsey for calling me on it--I really should have known better.

I still don't really recommend doing this sort of thing without good reason, but it's not as bad as I made it sound. Mea culpa.

这篇关于链接/组合Haskell中的类型类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆