如何为函子参数化的自定义类型实现类似Traversable的高阶遍历能力
你需要的高阶类型遍历抽象属于高阶 Kind 数据(Higher-Kinded Data, HKD)模式的标准能力,当前生态已有成熟的通用实现,不需要手动写定制转换函数。
方法1:使用通用HKD抽象类
目前社区有两个常用的依赖提供对应的抽象:
hkd库的HTraversable类barbies库的TraversableB类
两者的使用逻辑完全一致,只需要让你的 Foo 类型派生通用实例,就可以直接调用内置的反转方法:
{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-} import GHC.Generics (Generic) import Data.HKD (HTraversable(..), Identity(..)) import Data.List.NonEmpty (NonEmpty) -- 你的参数化Foo类型,直接派生通用实例即可 data Foo f = Foo { x :: f Int , y :: f Int , others :: f (NonEmpty Int) } deriving (Generic, HTraversable) -- 直接用hsequence完成Foo Maybe -> Maybe (Foo Identity)的转换 foo :: Input -> Maybe (Foo Identity) foo i = hsequence $ Foo (computeX i) (computeY i) (computeOthers i)
方法2:零依赖轻量实现
如果不想引入额外依赖,也可以直接基于Applicative实现通用的高阶组合子,所有同结构的HKD类型都可以复用:
liftFoo :: Applicative f => Foo f -> f (Foo Identity) liftFoo (Foo x y o) = Foo <$> (Identity <$> x) <*> (Identity <$> y) <*> (Identity <$> o)
这种实现和你之前用liftA3的逻辑完全等价,只是封装成了独立的通用方法。
内容的提问来源于stack exchange,提问作者amalloy
相关产品推荐
相关产品推荐

