为类类的子类定义方法

时间:2014-02-15 15:53:44

标签: haskell typeclass

我试过了:

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'

如何为fmapApplicative的其他子类定义Functor

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:8)

你理解这个错误:没有任何子类概念在任何地方播放。

如果存在类约束:class (Functor f) => Applicative f,则意味着要将某个类型定义为Applicative实例,它应该已经 Functor的实例{1}}。

考虑数据类型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的新函数,因为它具有类约束。类约束只是告诉您Applicative实例应该已经是Functor类型类的实例。您必须在创建fmap实例时定义Functor函数,因为这是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