2017-02-05 33 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實例。