如何对函数进行逆向映射?

时间:2016-08-12 17:56:02

标签: haskell contravariance

假设:

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

以下代码被拒绝。由于String -> BoolInt -> Bool的对立映射,我期望获得String -> Int(谓词)。我觉得愚蠢,因为我必须做出一些错误的假设。请帮助我理解错误消息。为什么第二个论点应该与我认为需要的那个不同?

Prelude Control.Lens> contramap length (>0) "Hello"

<interactive>:25:19: error:
    • Couldn't match type ‘Bool’ with ‘Int’
      Expected type: [Char] -> Int
        Actual type: [Char] -> Bool
    • In the second argument of ‘contramap’, namely ‘(> 0)’
      In the expression: contramap length (> 0) "Hello"
      In an equation for ‘it’: it = contramap length (> 0) "Hello"

2 个答案:

答案 0 :(得分:9)

Contravariant仅适用于类型构造函数的最后一个参数。您可能需要Profunctor,它表示在倒数第二个参数中具有逆变性的类型构造函数和在最后一个参数中的协变(如常规函数)。

<Gurkenglas> > lmap length (>0) "hello"
<lambdabot>  True

答案 1 :(得分:5)

实际上,你正在寻找无聊的旧协变Functor实例。

> fmap (>0) length "Hello"
True

在更高级别,您可能正在寻找null功能。对于许多类型,length将遍历您传递给它的整个数据结构,而null通常不会。{/ p>

以下是错误消息的简短说明。第一:

contramap length :: (Contravariant f, Foldable t) => f      Int  -> f (t a)
(>0)             :: (Num a, Ord a) =>                (->) a Bool

我已经将事情与我希望是一种暗示性的方式结合起来。要将contramap length应用于(>0),我们需要设置f ~ (->) aInt ~ Bool。第二个显然是不可能的,所以编译器抱怨。 (注意:第一个等式只是微妙的不可能;即使你提供的函数返回Int你也有问题,但编译器还没注意到,因为第二个等式的明显问题胜过它。即:Contravariant没有(->) a个实例,但不能!{/ p>