这里说的是[]和Maybe这样的类型构造函数的组合,而不是fmap这样的函数组合。所以比如[]和Maybe有两种组合方式:
newtype ListOfMabye a = ListOfMaybe [Maybe a]
newtype MaybeOfList a = MaybeOfList (Maybe [a])
两个Functors 的组合是Functor 的说法意味着有一种公式化的方式可以为这些类型编写一个Functor 实例:
instance Functor ListOfMaybe where
fmap f (ListOfMaybe x) = ListOfMaybe (fmap (fmap f) x)
instance Functor MaybeOfList where
fmap f (MaybeOfList x) = MaybeOfList (fmap (fmap f) x)
事实上,Haskell 平台附带了 Data.Functor.Compose 模块,它为您提供了一个 Compose 类型,可以“免费”执行此操作:
import Data.Functor.Compose
newtype Compose f g a = Compose { getCompose :: f (g a) }
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
Compose 对于GeneralizedNewtypeDeriving 扩展特别有用:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype ListOfMaybe a = ListOfMaybe (Compose [] Maybe a)
-- Now we can derive Functor and Applicative instances based on those of Compose
deriving (Functor, Applicative)
请注意,两个Applicatives 的组合也是一个Applicative。因此,由于[] 和Maybe 是Applicatives,所以Compose [] Maybe 和ListOfMaybe 也是。编写Applicatives 是一种非常巧妙的技术,如今它正慢慢变得越来越普遍,在您不需要 monad 的全部功能的情况下,它可以替代 monad 转换器。