2014-02-15 58 views
5

我試過這個方法:定義類型類的子類

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 
class (Functor f) => Applicative f where 
    pure :: a -> f a 
    (<*>) :: f (a -> b) -> f a -> f b 
    fmap f x = pure f <*> x 

我得到這個:

`fmap' is not a (visible) method of class `Applicative' 

如何定義fmapFunctorApplicative和其他子類?

+0

'(<$>)'已經沒有,它是中綴版本'fmap' –

回答

9

您要求的內容尚未針對Haskell實施。然而,對於這種所謂的Default Superclass Instances功能的建議,這樣可以讓你做聲明:

class Functor f => Applicative f where 
    return :: x -> f x 
    (<*>) :: f (s -> t) -> f s -> f t 

    instance Functor f where 
    fmap = (<*>) . pure 
8

你正在理解這個錯誤:沒有任何子類概念在任何地方玩。

當有一個類約束是這樣的:class (Functor f) => Applicative f,這意味着用於定義某種類型是一個Applicative情況下,它應該是已經Functor一個實例。

考慮數據類型Maybe

你這樣定義它的Functor實例:

instance Functor Maybe where 
    fmap _ Nothing  = Nothing 
    fmap f (Just a)  = Just (f a) 

及其Applicative實例是這樣的:

instance Applicative Maybe where 
    pure = Just 
    (Just f) <*> (Just x) = Just (f x) 
    _  <*> _  = Nothing 

如例子中看出上面,你無法定義名爲fmap的新功能Applicative實例只是b因爲它有它的階級約束。類約束只是告訴你,Applicative實例應該已經是Functor typeclass的一個實例。您必須在創建Functor實例時定義fmap函數,因爲這是Functor類型類型需要的,但不是Applicative之一。

此外,您的類型類應該是這樣的:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

class (Functor f) => Applicative f where 
    pure :: a -> f a 
    (<*>) :: f (a -> b) -> f a -> f b 

你並不需要把fmap附加到Applicative類型類也。類約束意味着具有Applicative的所有類型都需要定義fmap

+0

所以這是繼承手段。 – ThePiercingPrince

+4

@ThePiercingPrince我已經更新瞭解釋。如果不嘗試在OOP語言繼承和Haskell之間找到類比,那更好。 – Sibi

相關問題