Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 在逆变函子的实例声明中删除类型同义词_Haskell - Fatal编程技术网

Haskell 在逆变函子的实例声明中删除类型同义词

Haskell 在逆变函子的实例声明中删除类型同义词,haskell,Haskell,如果我定义: class Contravariant f where contramap :: (b -> a) -> f a -> f b type Op r a = (->) a r 并希望定义: instance Contravariant (Op r) where contramap f g = g . f 我得到的错误是实例类型不能是同义词。所以我想我需要一些类似于: instance Contravariant ((->) _ r)

如果我定义:

class Contravariant f where
    contramap :: (b -> a) -> f a -> f b

type Op r a = (->) a r
并希望定义:

instance Contravariant (Op r) where
    contramap f g = g . f
我得到的错误是实例类型不能是同义词。所以我想我需要一些类似于:

instance Contravariant ((->) _ r) where
    contramap f g = g . f

这当然行不通。如何使这个逆变实例工作?

根据注释,通常的方法是定义一个
newtype
。请注意,语法与定义
数据
类型基本相同,只是使用
newtype
代替
数据
,并且只允许一个字段。特别是,您需要一个构造函数,它通常与类型同名:

newtype Op r a =   Op      (a -> r)
--      ^^         ^^      ^^^^^^^^
--    newtype  constructor  field
这具有定义与
a->r
同构的类型的效果,但是类型参数
a
在完整类型
Op r a
中位于“最后”,这允许您为
Op r
定义一个
逆变
实例。请注意,您需要在适当的地方展开和包装构造函数:

instance Contravariant (Op r) where
  contramap f (Op g) = Op (g . f)
要进一步证明这是正确的方法,请注意,来自
base
的in
Data.Functor.Contravariant
已经这样设置,除非他们决定使用字段访问器
getOp

-- from the Data.Functor.Contravariant source

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

instance Contravariant (Op a) where
  contramap f g = Op (getOp g . f)

根据注释,通常的方法是定义
newtype
。请注意,语法与定义
数据
类型基本相同,只是使用
newtype
代替
数据
,并且只允许一个字段。特别是,您需要一个构造函数,它通常与类型同名:

newtype Op r a =   Op      (a -> r)
--      ^^         ^^      ^^^^^^^^
--    newtype  constructor  field
这具有定义与
a->r
同构的类型的效果,但是类型参数
a
在完整类型
Op r a
中位于“最后”,这允许您为
Op r
定义一个
逆变
实例。请注意,您需要在适当的地方展开和包装构造函数:

instance Contravariant (Op r) where
  contramap f (Op g) = Op (g . f)
要进一步证明这是正确的方法,请注意,来自
base
的in
Data.Functor.Contravariant
已经这样设置,除非他们决定使用字段访问器
getOp

-- from the Data.Functor.Contravariant source

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

instance Contravariant (Op a) where
  contramap f g = Op (getOp g . f)

尝试使用newtype而不是type来定义Op。我不是hs方面的专家,但是type只创建一个别名。newtype的构造函数必须只有一个字段。@vkubicki您的类型只有一个字段,所以这不是障碍。它有两个类型参数,那又怎样?任何
type
同义词都可以转换为
newtype
,因为它们都只有一个字段限制。这就是我在
newtype Op r a=(->)a r中得到的错误
newtype Op r a=Op(a->r)
相当于
newtype Op r a=Op((->)a r)
尝试使用newtype而不是type来定义Op。我不是hs方面的专家,但是type只创建一个别名。newtype的构造函数必须只有一个字段。@vkubicki您的类型只有一个字段,所以这不是障碍。它有两个类型参数,那又怎样?任何
类型
同义词都可以转换为
新类型
,因为它们都只有一个字段限制。这就是我在
新类型Op r a=(->)a r时遇到的错误
新类型Op r a=Op(a->r)
等同于
新类型Op r a=Op((->)a r