如果类型参数的顺序错误,是否可以使类型成为类的实例? [英] Is it possible to make a type an instance of a class if its type parameters are in the wrong order?

查看:90
本文介绍了如果类型参数的顺序错误,是否可以使类型成为类的实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



  data SomeType ma = SomeType(m Integer)[a] 

code>

我们可以用下面的代码轻松地将该类型作为Functor的一个实例:

 实例Functor(SomeType m)其中
fmap f(SomeType m lst)= SomeType m(map f lst)

然而,如果 SomeType 类型的参数被交换:

  data SomeType2 am = SomeType2(m整数)[a] 

然后上面的实例定义不起作用。



是否有某种方法可以使 SomeType2 Functor的一个实例?如果不是的话,那么Haskell / ghc会有什么新增和增加的功能吗?

解决方案

我有偏见,但我认为这是利用一个很好的机会Control.Newtype ,这是一款仅仅是cabal install newtype的小套件。



这是这笔交易。你想要在类型构造函数中进行翻转,以便在另一个参数中使用函数(例如)。定义新类型

  newtype Flip fxy = Flip(fyx)

并将它添加到 Newtype 类中,从而

实例Newtype(Flip fxy)(fyx)其中
pack = Flip
unpack(Flip z)= z
pre>

Newtype 类只是一个将newtypes映射到它们未被修饰的等价物的目录,提供了方便的工具包,例如 op Flip Flip 的倒数:您不需要记住所谓的名称。



对于有问题的问题,我们现在可以做这样的事情:

  data Bif xy = BNil | BCons xy(Bif xy)派生Show 

这是一个两参数数据类型,它恰好在两个参数中都是函数。 (可能,我们应该将它作为Bifunctor类的一个实例,但无论如何...)我们可以使它成为 Functor 两次:一次用于最后一个参数... (Bif x)其中
fmap f BNil = BNil
fmap f(BCons xyb)

pre $ = BCons x(fy)(fmap fb)

...第一次:

 实例Functor(Flip Bif y)其中
fmap f(Flip BNil)=翻转BNil
fmap f Flip(BCons xyb))= Flip(BCons(fx)y(Flip(fmap f)b))

其中在pf 之下是说< op p的简单方式。 F 。 p 。



我告诉你没有谎言:让我们试试。

  someBif :: Bif Int Char 
someBif = BCons 1'a'(BCons 2'b'(BCons 3'c'BNil))

然后我们得到

  * Flip> fmap succ someBif 
BCons 1'b'(BCons 2'c'(BCons 3'd'BNil))
* Flip>在Flip下(fmap succ)someBif
BCons 2'a'(BCons 3'b'(BCons 4'c'BNil))

在这些情况下,真正有很多方法可以将同一个事物看作 Functor ,所以我们必须做出正确的决定一些噪音来说明我们的意思。但如果你有系统的话,噪音并不是那么重要。

Consider the following type:

data SomeType m a = SomeType (m Integer) [a]

We can easily make that type an instance of Functor with the following code:

instance Functor (SomeType m) where
  fmap f (SomeType m lst) = SomeType m (map f lst)

However, if instead the params of the SomeType type were swapped:

data SomeType2 a m = SomeType2 (m Integer) [a]

Then the above instance definition doesn't work.

Is there some way of making SomeType2 an instance of Functor? If not, are there any up and coming additions to haskell/ghc that would make it possible?

解决方案

Biased am I, but I think this is a great opportunity to make use of Control.Newtype, a little piece of kit that's a mere "cabal install newtype" away.

Here's the deal. You want to flip around type constructors to get your hands on functoriality (for example) in a different parameter. Define a newtype

 newtype Flip f x y = Flip (f y x)

and add it to the Newtype class thus

 instance Newtype (Flip f x y) (f y x) where
   pack = Flip
   unpack (Flip z) = z

The Newtype class is just a directory mapping newtypes to their unvarnished equivalents, providing handy kit, e.g. op Flip is the inverse of Flip: you don't need to remember what you called it.

For the problem in question, we can now do stuff like this:

 data Bif x y = BNil | BCons x y (Bif x y) deriving Show

That's a two parameter datatype which happens to be functorial in both parameters. (Probably, we should make it an instance of a Bifunctor class, but anyway...) We can make it a Functor twice over: once for the last parameter...

instance Functor (Bif x) where
  fmap f BNil = BNil
  fmap f (BCons x y b) = BCons x (f y) (fmap f b)

...and once for the first:

instance Functor (Flip Bif y) where
  fmap f (Flip BNil) = Flip BNil
  fmap f (Flip (BCons x y b)) = Flip (BCons (f x) y (under Flip (fmap f) b))

where under p f is a neat way to say op p . f . p.

I tell you no lies: let us try.

someBif :: Bif Int Char
someBif = BCons 1 'a' (BCons 2 'b' (BCons 3 'c' BNil))

and then we get

*Flip> fmap succ someBif
BCons 1 'b' (BCons 2 'c' (BCons 3 'd' BNil))
*Flip> under Flip (fmap succ) someBif
BCons 2 'a' (BCons 3 'b' (BCons 4 'c' BNil))

In these circumstances, there really are many ways the same thing can be seen as a Functor, so it's right that we have to make some noise to say which way we mean. But the noise isn't all that much if you're systematic about it.

这篇关于如果类型参数的顺序错误,是否可以使类型成为类的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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