2017-02-05 31 views
1

我经历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的情况下工作?

回答

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) 3相同2 + 3((->) X) Y相同X -> Y(这是咖喱运营商的应用程序,它甚至可以在类型级别的工作):

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

我们可以读出上面的签名为“给出一个函数从ab和从ta的函数,从t返回到b的函数“。

现在你只需要实现它。 :-)

2

我们定义Functor实例作为这样的:

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

也就是说,该(->)函子相当于通过获取a型的一些价值只能被“开”的容器和用它打开容器。任何fmap然后只是在“打开”容器后更改值。即:撰写功能。

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

但请记住,所有的单子都是仿函数,因为我们可以只定义fmap像这样:

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

所以,如果你明白是什么将在Monad情况下做到这一点应该清楚它的作用在Functor实例。