仿函数实例声明中的箭头运算符?

时间:2017-02-05 16:38:34

标签: haskell functor

我正在通过these Haskell'中间'练习,我做了以下几个实例:

class Fluffy f where
  furry :: (a -> b) -> f a -> f b

instance Fluffy [] where
  furry f [] = []

instance Fluffy Maybe where
  furry f (Just e) = Just (f e)
  furry f (Nothing) = Nothing

然而,第三个问题语法让我感到难过:

instance Fluffy ((->) t) where
  ...

我已经阅读了箭头操作符并阅读了this的答案,该答案解释了(->)在Monad实例中的作用。但是,我不太了解(->)在Functors的上下文中是如何工作的?

2 个答案:

答案 0 :(得分:9)

我们有:

class Fluffy f where
  furry :: (a -> b) -> f a -> f b

我们要定义:

instance Fluffy ((->) t) where
  furry = ...

这意味着在上面的实例中,furry应该具有(a -> b) -> f a -> f b类型f ((->) t),或者换句话说:

furry :: (a -> b) -> ((->) t) a -> ((->) t) b

正如((+) 2) 32 + 3相同,((->) X) YX -> Y相同(它是咖喱运算符应用程序,甚至可以在类型级别工作):< / p>

furry :: (a -> b) -> (t -> a) -> (t -> b)

我们可以将上述签名读作“ab的函数以及从ta的函数,从{返回函数{1}}至t “。

现在你必须实现它。 : - )

答案 1 :(得分:2)

我们将Functor实例定义为:

instance Functor ((->) a) where
    fmap f g = \a -> f (g a)
    -- Pointfree definition: fmap = (.)

也就是说,(->)仿函数可以与只能通过获取类型a的某个值并使用它打开容器“打开”的容器相媲美。然后,任何fmap只是在我们“打开”容器后更改值。即:编写功能。

这有点像Maybe仿函数,因为我可以将函数应用于值(如果它存在),但对于(->)仿函数我在做之前就知道它是什么。

但请记住,所有monad都是仿函数,因为我们可以这样定义fmap

fmap f m = m >>= (\a -> return (f a))

因此,如果您了解Monad实例中的内容,则应明确其在Functor实例中的作用。