Haskell 学习笔记三:Functors

Functors, Applicatives 和 Monads

这里估计是最劝退的地方了,我会尽量用简单的语言描述。网上的很多资源说得太复杂了,天知道劝退了多少人,我第一次看的时候完全看不懂他们在说什么。

Functors

问:什么是 Functors?

我的回答:Functor 说白了就是一种属性(准确来说叫 typeclass,你把它想象成 Java 的 Interface),Functor 里面包着另外一个数据。一个数据类型只要实现了这个属性就是 Functor

超级简单是不是?就像一个盒子,盒子里面是另外一个东西。这个盒子就是 Functor。

举个例子就好理解多了。Haskell 有内置一个数据类型叫 Maybe(就是 Java 的 Optional,Haskell 太先进了以至于大家都要抄),是这样的:

data Maybe a = Nothing | Just a

是不是真的和 Java 的 Optional 一模一样,要么没有(Nothing),要么有(Just a)。

一个 functor 必须实现以下的函数:

class Functor f where

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

class 在这里是 typeclass 的关键字,同样你把它想象成 interface。

fmap 是一个函数,参数是一个函数和一个 functor。fmap 会把 functor 里面的值喂给这个函数,返回的结果包在一个新的 functor 里。它和 <$> 是同义词(想象成 C 的 #define),一模一样。fmap a b 可以写成 a <$> b

想象一下,盒子里面有一个老婆。老婆被拿出来做成了老婆饼。老婆饼被装进了一个新的盒子并返回。

回到刚才那个 Maybe 的例子。Maybe 作为一个 Functor,就实现了这几个函数。具体的实现代码是这样的:

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

超级简单是不是。不要被 instance Functor 吓到,其实就是 Java 的 implements Functor

上手试试吧:

Main> fmap (+1) (Just 0)
Just 1

在这里,盒子是(Just 0)。盒子里面装着老婆(0)。老婆(0)被做(+1)成了老婆饼(1)。老婆饼(1)被装进了盒子(Just 1)并且出货了。

你甚至还可以 fmap (+) (Just 1),这样出来的就是一个装着函数的盒子。仔细想想,它其实是符合类型签名的。

你肯定懂了。

下一集:Haskell 学习笔记四:Applicative