尝试了解Haskell中的Applicative

时间:2018-11-18 00:38:15

标签: haskell

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

我试图理解Haskell中的适用性 根据适用性的定义,它看起来像 Functor

的子类。

我认为fmap就像Functor的接口(在Java世界中) 如果来自Functor的 Applicative 子类,则需要实现Functor的fmap,但是 Functor Applicative 中的fmap签名不同

(a -> b) -> f a -> f b
f (a -> b) -> f a -> f b

谁能解释为什么?

3 个答案:

答案 0 :(得分:5)

首先,如@paul所述,您正在使用的定义有些偏离。正确的定义如下:

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

那么这些定义应该如何解码?在这里要实现的主要事情是,与Java接口相比,Haskell类型类与Java接口有更多的共同点-因此,这里的Applicative定义不是在Java意义上定义子类,而是指定类型只能是一个实例。 Applicative的值,如果它已经是Functor的实例(即,所有Applicative也必须实现fmap,即使它不是Applicative类型类的一部分)。有关FunctorApplicative的更多信息,我强烈推荐在线图​​书Learn You a Haskell for Great Good,尤其是section on 'Functors, Applicative and Monoid'

答案 1 :(得分:4)

请参阅Control.Applicative的文档。

的类型签名
(<*>) :: f (a -> b) -> f a -> f b

是顺序应用程序运算符<*>而不是fmap

  

我认为fmap就像Functor的接口(在Java世界中),如果   Functor的应用子类,则需要从   函子

实际上,Applicative就像Java世界中的接口,更确切地说,就像Java自8以来引入的带有default methods的接口。在Java语法中,如:

public interface Applicative extends Functor {..}

请注意,此处Java中Applicative的定义不是一个具体的类,它不需要不需要fmap接口实现Functor

答案 2 :(得分:3)

我认为您正在使用的定义有些偏离(可能是来源有误,或者您可能误解了),这就是造成混淆的原因。

就像@AJFarmar在评论中提到的那样,fmapFunctor类型类(或Java术语为Interface)的一部分; Applicative的定义表明,每当您尝试创建一个Applicative实例(即实现Applicative接口)时,您都将尝试为也创建该实例的类型< / em>必须是Functor的实例(它还必须实现Functor接口)。因此fmap的签名将始终为:

fmap :: (a -> b) -> f a -> f b