算子的"换位"?

Phi*_*sky 6 haskell functor category-theory

最近我不得不写下面这个函数:

mToL :: Maybe [a] -> [Maybe a]
mToL Nothing = []
mToL (Just xs) = map Just xs
Run Code Online (Sandbox Code Playgroud)

这就提出了一个问题:是否有可能将上述内容概括为:

transposeF :: (Functor f, Functor g) => f (g a) -> g (f a)
Run Code Online (Sandbox Code Playgroud)

我想,如果有一种方法来"崩溃"它只能f (g a)f a,或有任何其他方式?

Nik*_*kov 13

Traversable类型类提供sequencesequenceA运营,提供最通用的解决你的问题,但它们需要不同的约束:

sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
Run Code Online (Sandbox Code Playgroud)


aco*_*mar 10

这一般是不可能的,不是.设置fConst bgIdentity.

newtype Const b a = Const { getConst :: b }
newtype Identity a = Identity { runIdentity :: a }
Run Code Online (Sandbox Code Playgroud)

这些都是具有正常实例的显然算子.transposeF无法工作,因为Const b不提供任何a用于包装身份的s.所以你不能写转置函数.

另一方面,这对于很多Functor配对来说都很不错.分类概念是伴随仿函数的概念,一旦你看到它们,你就会开始到处看到它们.它们本身就是一个非常强大的概念.


Dan*_*zer 8

实际上,有一个类型类可以支持这个.它不包含在标准类型类中,但"可表示的仿函数"具有此功能.

代表性的仿函数是一个F有两件事的仿函数

  1. 一种 A
  2. F和之间的同构(->) A

我们可以将此表示为

 type family ReprObj (f :: * -> *):: *

 class Functor f => Repr f where
   toHom   :: f a -> (ReprObj f -> a)
   fromHom :: (ReprObj f -> a) -> f a
Run Code Online (Sandbox Code Playgroud)

哪里toHom . fromHom = fromHom . toHom = id.可表示的仿函数的一个例子,

 newtype Pair a = Pair (a, a) deriving Functor
 type instance ReprObj Pair = Bool

 instance Repr Pair where
   toHom (Pair (a, b)) True  = a
   toHom (Pair (a, b)) False = b
   fromHom f = Pair (f True, f False)
Run Code Online (Sandbox Code Playgroud)

现在使用这个我们可以推导出来

swap :: (Functor f, Functor g, Repr f, Repr g) => f (g a) -> g (f a)
swap g = fromHom $ \obj -> fmap ($ obj) hom
   where hom = fmap toHom g
Run Code Online (Sandbox Code Playgroud)

事实上,我们也可以从可表示的仿函数中获得一个免费的applicative和monad实例.我详细介绍了如何在博文中做到这一点.