如何编写map / fmap analogue(a-> b) - > F m a - > F m b

时间:2017-06-17 09:28:49

标签: haskell

大家好日夜! 我有类型:

data FixItem m a = KeepItem|SkipItem|FixItem (m (a -> a))
fixItem f = FixItem $ pure f

我想编写函数mapFix :: (a -> b) -> FixItem m a -> FixItem m b。当我尝试:

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

所以,我得到错误:

    • 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)

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

1 个答案:

答案 0 :(得分:4)

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

虽然您可以为您的数据类型实施Invariant。由于协变逆变位置均为a,因此您的数据类型是不变函子。

可以帮到你:

Example of Invariant Functor?

What is a contravariant functor?

Some blog post