如果类型参数的顺序错误,是否可以使类型成为类的实例?

Dav*_*ani 17 haskell

请考虑以下类型:

data SomeType m a = SomeType (m Integer) [a]
Run Code Online (Sandbox Code Playgroud)

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

instance Functor (SomeType m) where
  fmap f (SomeType m lst) = SomeType m (map f lst)
Run Code Online (Sandbox Code Playgroud)

但是,如果相反SomeType类型的参数被交换:

data SomeType2 a m = SomeType2 (m Integer) [a]
Run Code Online (Sandbox Code Playgroud)

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

有没有办法制作SomeType2Functor的实例?如果没有,那么haskell/ghc是否有任何新增功能可以实现?

pig*_*ker 20

我有偏见,但我认为这是一个很好的机会,可以使用Control.Newtype,这是一个仅仅是"cabal install newtype"的小工具.

这是交易.您想要翻转类型构造函数,以便在不同的参数中获得有趣的(例如).定义一个新类型

 newtype Flip f x y = Flip (f y x)
Run Code Online (Sandbox Code Playgroud)

并将其添加到Newtype类中

 instance Newtype (Flip f x y) (f y x) where
   pack = Flip
   unpack (Flip z) = z
Run Code Online (Sandbox Code Playgroud)

Newtype类只是一个目录映射newtypes他们质朴的等价物,提供方便的工具包,例如op Flip是逆Flip:你不必记得你的说法.

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

 data Bif x y = BNil | BCons x y (Bif x y) deriving Show
Run Code Online (Sandbox Code Playgroud)

这是一个两参数数据类型,恰好在两个参数中都是函数式的.(或许,我们应该把它作为Bifunctor类的一个实例,但无论如何......)我们可以使它成为Functor两次:一次用于最后一个参数......

instance Functor (Bif x) where
  fmap f BNil = BNil
  fmap f (BCons x y b) = BCons x (f y) (fmap f b)
Run Code Online (Sandbox Code Playgroud)

......和第一次:

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))
Run Code Online (Sandbox Code Playgroud)

这里under p f是一个整洁的方式来表达op p . f . p.

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

someBif :: Bif Int Char
someBif = BCons 1 'a' (BCons 2 'b' (BCons 3 'c' BNil))
Run Code Online (Sandbox Code Playgroud)

然后我们得到

*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))
Run Code Online (Sandbox Code Playgroud)

在这种情况下,有很多方法可以将同一件事视为a Functor,所以我们必须发出一些声音来说明我们的意思.但是如果你对它有系统的话,噪音并不是那么多.

  • 原问题的答案是"不".或者至少,不是在Haskell.在某种程度上,如果答案是肯定的,那么提出一个解决方案是很奇怪的. (2认同)