Haskell 如何编写map/fmap模拟(a->;b)->;F m a->;F m b

Haskell 如何编写map/fmap模拟(a->;b)->;F m a->;F m b,haskell,Haskell,大家好! 我有以下类型: data FixItem m a = KeepItem|SkipItem|FixItem (m (a -> a)) fixItem f = FixItem $ pure f 我想写函数mapFix::(a->b)->fixitemma->fixitemmb。当我尝试时: mapFix f SkipItem = SkipItem -- good mapFix f KeepItem = fixItem f -- error "rigid type"!!! mapFi

大家好! 我有以下类型:

data FixItem m a = KeepItem|SkipItem|FixItem (m (a -> a))
fixItem f = FixItem $ pure f
我想写函数
mapFix::(a->b)->fixitemma->fixitemmb
。当我尝试时:

mapFix f SkipItem = SkipItem -- good
mapFix f KeepItem = fixItem f -- error "rigid type"!!!
mapFix f (FixItem mf) = FixItem $ pure (.) <*> (pure f) <*> mf -- too!

如何为此类类型编写mapFix或实现Functor实例(FixItem将
a
修复为
a
,而不是
b
,即修复是
a->a
,而不是
a->b
)?

您不能为您的数据类型实现
Functor
类型类。是因为
a->a
在一个构造函数中。当你有功能时,你应该更加小心。但简而言之,类型变量
a
处于逆变位置,因此无法对该类型变量实现
Functor

尽管您可以为您的数据类型实现。因为
a
处于协变和逆变位置,所以您的数据类型是不变函子

可以帮助您:


您不能为您的数据类型实现
Functor
类型类。是因为
a->a
在一个构造函数中。当你有功能时,你应该更加小心。但简而言之,类型变量
a
处于逆变位置,因此无法对该类型变量实现
Functor

尽管您可以为您的数据类型实现。因为
a
处于协变和逆变位置,所以您的数据类型是不变函子

可以帮助您:


我怀疑函子是不可能的,那么这是否意味着
mapFix
函数也是不可能的呢?顺便说一句,当我将类型更改为
FixItem ma b=FixItem(m(a->b))| SkipItem | KeepItem
并尝试实现Functor时,我再次遇到了关于正确类型“a”的错误…嗯,我得到了:FixItem中
纯f
mf
的组合隐藏
a->b
,而FixItem只支持
a->a
。所以,mapFix是不可能的。但是有可能实现
fixitemm a b=FixITem(m(a->b))|…
Functor实例吗?啊,好的,完成:)
fmap f(FixITem mf)=FixITem$pure()(pure f)mf
。谢谢@是的,函子在理论上是不可能的。这意味着
mapFix
功能也不可能实现:(如果您将
a->a
更改为
a->b
并具有类型
FixItem ma b
,则可以编写
mapFix
,当给定
b->c
函数时,该函数可以将
FixItem ma b
映射到
FixItem ma c
,因为
b
类型变量处于协变位置。我怀疑函子是冒充的。)ble,那么这是否意味着
mapFix
功能也不可能实现?顺便说一句,当我将类型更改为
FixItem m a b=FixItem(m(a->b))时|SkipItem | KeepItem
并尝试实现Functor,我再次得到关于正确类型“a”的错误…嗯,我得到了:组合
纯f
mf
在FixITem中隐藏
a->b
,而FixITem只支持
a->a
。因此,mapFix是不可能的。但是有可能实现
FixITem m=FixITem(m)吗(a->b);…
函子实例?啊,好的,完成:)
fmap f(FixItem mf)=FixItem$pure()(pure f)mf
。谢谢!@Paul AG是的,函子在某种理论意义上是不可能的。这意味着
mapFix
函数也是不可能的:(如果您将
a->a
更改为
a->b
,并且具有类型
fixab
,则可以编写
mapFix
,当给定
b->c
函数时,该函数可以将
fixab
映射到
fixac
,因为
b
类型变量处于协变位置。
    • Couldn't match type ‘b’ with ‘a’
      ‘b’ is a rigid type variable bound by
        the type signature for:
          mapFix :: forall (m :: * -> *) a b.
                    Applicative m =>
                    (a -> b) -> FixItem m a -> FixItem m b
        at src/test.hs:235:11
      ‘a’ is a rigid type variable bound by
        the type signature for:
          mapFix :: forall (m :: * -> *) a b.
                    Applicative m =>
                    (a -> b) -> FixItem m a -> FixItem m b
        at src/test.hs:235:11
      Expected type: b -> b
        Actual type: a -> b
    • In the first argument of ‘fixItem’, namely ‘f’
      In the expression: fixItem f
      In an equation for ‘mapFix’: mapFix f KeepItem = fixItem f
    • Relevant bindings include
        f :: a -> b (bound at src/test.hs:236:8)
        mapFix :: (a -> b) -> FixItem m a -> FixItem m b
          (bound at src/test.hs:236:1)