如果类型参数的顺序错误,是否可以使类型成为类的实例? [英] Is it possible to make a type an instance of a class if its type parameters are in the wrong order?
问题描述
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
之下是说<
我告诉你没有谎言:让我们试试。
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屋!