2017-06-17 77 views
1

好日/夜大家! 我有型:如何写地图/ fmap模拟(a-> b) - > F m a - > F m b

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或实现函子实例这种类型(FixItem修复aa,不b,IE修复是a -> a ,而不是a -> b)?

回答

4

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

尽管您可以为您的数据类型实施Invariant。因为a协变逆变职位,您的数据类型是不变的函子。

可以帮助您:

Example of Invariant Functor?

What is a contravariant functor?

Some blog post

+0

我怀疑函子是不可能的,所以这是不是意味着'mapFix'功能是不可能的呢?顺便说一句,当我改变类型为'FixItem mab = FixItem(m(a - > b))| SkipItem | KeepItem'并尝试实现Functor时,我再次得到有关正确类型'a'的错误... –

+0

嗯,我得到了它:在FixITem中,'纯f'和'mf'组成'a - > b',而FixItem仅支持'a - > a'。所以,mapFix是不可能的。但是可以实现'FixITem m a b = FixITem(m(a - > b))| ...'Functor实例吗? –

+0

啊,OK,完成:)'fmap f(FixItem mf)= FixItem $ pure(。)<*>(纯f)<*> mf'。谢谢! –

相关问题