其实这个区别就好像普通函数和高阶函数的区别一样。这样是不是很好理解了呢,额,如果你说你还不知道啥是高阶函数,那么还是不要看这个文章了。下面来看看我是如何把他们类比起来的。
我们看看haskell中的Eq是如何定义的,这个我把它叫"普通typeclasses"(为了区分Functor typeclasses,我就这么叫它了:P),这里定义了一个typeclasses并且在这个typeclasses里面定义了一个行为,普遍的说法就是你可以把这个typeclasses想象成java的interface,而typeclasses的行为想象成interface里面的抽象方法。这里面a是一个类型变量,也就是可以使任何的类型。
class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y)
接着我们定义一个自己的数据类型
data TrafficLight = Red | Yellow | Green
既然我们把typeclasses想象成interface,那么它自然和interface一样可以实例化咯
instance Eq TrafficLight where Red == Red = True Green == Green = True Yellow == Yellow = True _ == _ = False
实例化的时候我们将typeclasses里面的a这个类型变量替换成了实际类型TrafficLight,记住这里是实际类型,因为这是我们要区分functor typeclasses的关键,这样就算是定义了一个普通typeclasses和实现了Eq的instance。
然后我们定义一个Functor typeclasses,看看它是如何定义的。
class Functor f where fmap :: (a -> b) -> f a -> f b
定义数据类型,我们就拿下面这个说事
data Maybe a = Just a | Nothing
咦,这里在定义数据类型的时候多了个a,如何区别于前面定义的TrafficLig这个,正规官方的说法就是Maybe
是一个类型构造子,可接受一个类型作为参数,然后返回一个具体类型。我是这么理解的,TrafficLig就直接定义了具体类型给它,而Maybe,它需要接受一个类型变量a之后他才是一个具体类型,其实就是一个可接受一个类型的东东,就好像一个函数,需要接受一个值才能返回一个实际的值,只不过类型构造子是接受类型返回类型(我在内心对于没有副作用的函数多了一点理解,它接受一个值,构造出另外一个值返回给我们,这不正是函数的定义吗?这里指的是没有副作用的函数,使用这个函数仅仅是为了得到return的值,而且相同的输入每次都返回相同的输出)在接受一个类型之后它也就是具体类型了,比如Maybe是一个类型构造子,我们把类型变量a替换为Int传入进去之后Maybe Int这一整个东西就是一个具体类型啦。
再来看实例化Functor typeclasses。
instance Functor Maybe where fmap f (Just x) = Just (f x) fmap f Nothing = Nothing
果然和前面的普通typeclasses不一样,这里实例化的时候我们传入的是我们前面提到的类型构造子。漂亮,而前面那个普通的typeclasses接受的是什么?没错,是一个具体类型,我们发现了本质上的区别,我们再次来看下类型构造子和具体类型的区别。类型构造子是一个可接受一个类型作为参数,然后返回一个具体类型的东东。看看Maybe里面定义的函数fmap(fmap
接受一个函数,这个函数从一个类型映射到另一个类型,还接受一个 functor 装有原始的类型,然后会回传一个 functor 装有映射后的类型)。
这就把他和map这个高阶函数联系在了一起。我们来看看map的定义
map :: (a -> b) -> [a] -> [b]
他接受一个函数,这函数把一个类型的东西映射成另一个。还有一串装有某个类型的 List 变成装有另一个类型的 List。哇,和fmap好像。那么我们来看看List是如何被定义为functor的instance的。
instance Functor [] where fmap = map
哈哈哈,perfect,就是map函数。看清楚Functor后面传入的是一个[]而不是[a],这里[]就是一个类型构造子,接受一个具体类型之后返回具体类型,而[a]是一个具体类型。
而普通的函数就和普通的typeclasses一样,接受一个具体类型返回一个具体类型。
比如:
fun :: Int -> Int
接受一个Int类型返回一个Int类型。
看了这个之后是不是对于Functor这个typeclasses有了更深的理解呢:P