【问题标题】:How to write map/fmap analogue (a->b) -> F m a -> F m b如何编写 map/fmap 模拟 (a->b) -> F m a -> F m b
【发布时间】:2017-06-17 09:28:48
【问题描述】:

大家早安/晚安! 我有类型:

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 -&gt; a,而不是a -&gt; b)?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    您不能为您的数据类型实现Functor 类型类。这是因为 a -&gt; a 在您的一个构造函数中。当你有函数时,你应该更加小心。但简而言之,你有类型变量 a 在逆变位置,所以你不能在这个类型变量上实现 Functor

    虽然您可以为您的数据类型实现Invariant。因为acovariantcontravariant 位置,您的数据类型是不变函子。

    可以帮助你:

    Example of Invariant Functor?

    What is a contravariant functor?

    Some blog post

    【讨论】:

    • 我怀疑 Functor 是不可能的,那么这是否意味着mapFix 函数也不可能呢?顺便说一句,当我将类型更改为 FixItem m a b = FixItem (m (a -&gt; b))|SkipItem|KeepItem 并尝试实现 Functor 时,我再次收到关于正确类型“a”的错误...
    • 嗯,我明白了:pure fmf 的组合在 FixITem 中隐藏了 a -&gt; b,而 FixItem 仅支持 a -&gt; a。所以,mapFix 是不可能的。但是是否可以实现FixITem m a b = FixITem (m (a -&gt; b))|... Functor 实例?
    • 啊,好的,完成 :) fmap f (FixItem mf) = FixItem $ pure (.) &lt;*&gt; (pure f) &lt;*&gt; mf。谢谢!
    • @Paul-AG 是的,函子在某种理论上是不可能的。这意味着mapFix 函数也是不可能的:( 如果您将a -&gt; a 更改为a -&gt; b 并具有FixItem m a b 类型,那么您可以编写mapFix,当给定b -&gt; c 函数可以将FixItem m a b 映射到@ 987654346@ 因为b 类型变量处于协变位置。
    猜你喜欢
    • 2012-04-07
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 2022-01-13
    相关资源
    最近更新 更多