函子(Functor)

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


Sure you can do this. It’s just kinda reinventing the wheel. The advantage of standard classes is that everybody will make their types instances of them if appropriate, so if you write a function that can operate on a generic Functor f then it’ll work with a huge number of different type constructors f from hundreds of libraries. If you change the function to require MyDataFunctor f instead, it’ll do exactly the same thing, but only with your own type MyData.

The only sensible reason you might want to write your own class is if you want different behaviour

应用函子(Applicative)

f :: a -> b -> c
f a b c = ...
fmap f $Just a -- return: Just (b -> c) -- 或者我们自己定义一个 fmap f (Just a) (Just b) = Just$ f a b
fmap f Nothing _ = Nothing
fmap f _ Nothing = Nothing


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


class Applicative f => Manad f where
join :: m (m a) -> m a

return :: a -> m a
return = pure


-- 假设：a <$> f = fmap f a，注意：这里是和实际相反的。仅仅为了说明才这样写。 Just a <$> \a -> Just b <$> \b -> ...  由于 <$>最后返回的类型是Maybe b，则在第二段Just b <\$> \b -> ...的返回值也就是Maybe b，而对于lambda的要求是a -> b，类型是不匹配的。应用函子也差不多如此。因为只是相比于函子多处理了多参数的适配。