在Haskell中切换实例声明的参数顺序 [英] Switch order of arguments for instance declaration in Haskell

查看:80
本文介绍了在Haskell中切换实例声明的参数顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做一个实例声明,但是自由类型变量不是最后一个变量.例如,我有一个类声明

I want to make an instance declaration, but the free type variable is not the last variable. For example, I have a class declaration

class Poppable m where
  tryPop :: m a -> Maybe (a, m a)

现在,我要使Q.PSQ(优先级队列)成为Poppable的实例.具体来说,我想要这样的东西:

Now I want to make Q.PSQ (priority queue) an instance of Poppable. Specifically I want something like this:

instance (Ord p) => Poppable (\a -> Q.PSQ a p) where
  tryPop = fmap (first Q.key) . Q.minView

但是,这不是合法的Haskell代码.如果切换到PSQ的参数顺序,那么我将没有问题:

However, this is not legal Haskell code. If the order of arguments to PSQ were switched, then I would have no problem:

instance (Ord p) => Poppable (Q.PSQ p) where
  tryPop = fmap (first Q.key) . Q.minView

如何切换实例声明的参数顺序?

How do I switch the order of arguments for the instance declaration?

现在我可以用新类型包装PSQ:

Now I could wrap PSQ with a newtype:

newtype PSQ'' a b = PSQ'' (Q.PSQ b a)

但是对于我来说这似乎很笨拙,因为我必须不断地包装/拆开包装.有没有更简单的方法?

However this seems clunky to me because I have to constantly wrap/unwrap it. Is there an easier way?

*

我尝试使用数据/类型系列,但都给出了错误.

I tried using data/type families, but both give errors.

(1)使用数据族声明:

(1) Using a data family declaration:

data family PSQ' a b
data instance PSQ' a b = PSQ b a
instance (Ord p) => Poppable (PSQ' p) where
  tryPop = fmap (first Q.key) . Q.minView

但这会导致错误

Couldn't match type `Q.PSQ a p0' with `PSQ' p a'

即使可以通过设置p = p0进行匹配.

even though they can match by setting p=p0.

(2)类型族也不起作用.

(2) Type families won't work either.

type family PSQ' a b where
  PSQ' b a = Q.PSQ a b

给予

Illegal type synonym family application in instance: PSQ' p

推荐答案

现在我可以用新类型包装PSQ:

Now I could wrap PSQ with a newtype:

newtype PSQ'' a b = PSQ'' (Q.PSQ b a)

但是对于我来说这似乎很笨拙,因为我必须不断地包装/拆开包装.有没有更简单的方法?

However this seems clunky to me because I have to constantly wrap/unwrap it. Is there an easier way?

不是,不是真的.当然,您可以编写您的Poppable类以使其与PSQ相匹配.而且,如果您愿意,可以将新类型推广到

Nope, not really. You could, of course, write your Poppable class to make it match PSQ. And if you like, you can generalize your newtype to

newtype Flip f a b = Flip (f b a)

此时您可以写

instance Poppable (Flip Q.PSQ a)

但这些都不能消除潜在的烦恼因素.有原因的Haskell不支持此操作(显然,这使推理变得更加困难,有时甚至是不可能的,等等),因此您只需要处理它即可.

but none of this will get rid of the underlying annoyance factor. There are reasons Haskell doesn't support this (apparently, it makes inference much harder, sometimes impossible, etc.), so you'll just have to deal with it.

P.S.,这种类型的同义词可能更有用,与{-# LANGUAGE PolyKinds #-}一起使用,表示其含义

P.S., that type synonym may be more useful poly-kinded, with {-# LANGUAGE PolyKinds #-}, where it ends up meaning

newtype Flip (f :: k1 -> k2 -> *) (a :: k2) (b :: k1) = Flip (f b a)

这篇关于在Haskell中切换实例声明的参数顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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