类型同义词实例

vku*_*cki 1 haskell

阅读“程序员的范畴论”我试图为 Op 重新创建 Functor 类型类实例。

\n
{-# LANGUAGE TypeSynonymInstances #-}\n\nmodule Type.Op where\n\nimport Data.Functor.Contravariant ( Contravariant, contramap )\n\ntype Op r a = a -> r\n-- data Op r a = (->) a r\n\ninstance Contravariant (Op r) where\n    contramap f g = g . f\n
Run Code Online (Sandbox Code Playgroud)\n

编译产生以下错误:

\n
    \xe2\x80\xa2 The type synonym \xe2\x80\x98Op\xe2\x80\x99 should have 2 arguments, but has been given 1\n    \xe2\x80\xa2 In the instance declaration for \xe2\x80\x98Contravariant (Op r)\xe2\x80\x99\n   |\n10 | instance Contravariant (Op r) where\n   |          ^^^^^^^^^^^^^^^^^^^^\n
Run Code Online (Sandbox Code Playgroud)\n

我应该怎么办 ?对于正常情况,Functor我会以同样的方式使用部分类型......

\n

lef*_*out 5

让我们考虑一个更简单的类

class Unftor f where
  unfmap :: (a -> a) -> f a -> f a

instance Unftor ((->) x) where
  unfmap f g = f . g
Run Code Online (Sandbox Code Playgroud)

现在,如果你尝试做的事情是可能的,我可以写

instance Unftor (Op r) where
  unfmap f g = g . f
Run Code Online (Sandbox Code Playgroud)

...但是等等,让我们看看每种情况下的签名

instance Unftor ((->) x) where
  unfmap :: (a -> a) -> (x -> a) -> (x -> a)
instance Unftor (Op r) where
  unfmap :: (a -> a) -> Op r a -> Op r a
Run Code Online (Sandbox Code Playgroud)

由于Op只是一个类型同义词,因此与

instance Unftor (\a -> (a -> r)) where
  unfmap :: (a -> a) -> (a -> r) -> (a -> r)
Run Code Online (Sandbox Code Playgroud)

现在,选择所有类型的特殊情况Int

unfmap :: (Int -> Int) -> (Int -> Int) -> (Int -> Int)
unfmap f g = f . g   -- from `instance Unftor ((->) x)`
unfmap :: (Int -> Int) -> (Int -> Int) -> (Int -> Int)
unfmap f g = g . f   -- from `instance Unftor (Op r)`
Run Code Online (Sandbox Code Playgroud)

……同样的签名!但不知何故,编译器应该将它们分开?

那是行不通的。

相反,您需要做的是创建一个Opa -> r. 这正是 newtypes 的用途(data也可以):

newtype Op r a = Op {getOp :: a -> r}

instance Contravariant (Op r) where
    contramap (Op f) g = Op $ g . f
Run Code Online (Sandbox Code Playgroud)