【发布时间】:2017-10-26 13:02:07
【问题描述】:
在this answer 中,我当场编造了一些看起来有点像“高阶Traversable”的东西:就像Traversable,但对于从Hask 到Hask 的endofunctors 类别的函子。
{-# LANGUAGE RankNTypes #-}
import Data.Functor.Compose
import Data.Functor.Identity
class HFunctor t where
hmap :: (forall x. f x -> g x) -> t f -> t g
class HFunctor t => HTraversable t where
htraverse :: Applicative g => (forall x. f x -> g x) -> t f -> g (t Identity)
htraverse eta = hsequence . hmap eta
hsequence :: Applicative f => t f -> f (t Identity)
hsequence = htraverse id
我将HFunctor 设为HTraversable 的超类,因为它看起来是对的,但是当我坐下来写hmapDefault 时,我卡住了。
hmapDefault :: HTraversable t => (forall x. f x -> g x) -> t f -> t g
hmapDefault eta = runIdentity . htraverse (Identity . eta)
-- • Couldn't match type ‘x’ with ‘g x’
-- Expected type: f x -> Identity x
-- Actual type: f x -> Identity (g x)
Identity . eta 有一个类型forall y. f y -> Identity (g y),所以当我将它传递给htraverse g 与Identity 和x 统一时,必须与y 和g y 统一,所以它失败了因为遍历函数不是自然变换。
我尝试使用Compose 对其进行修补:
hmapDefault :: HTraversable t => (forall x. f x -> g x) -> t f -> t g
hmapDefault eta = runIdentity . getCompose . htraverse (Compose . Identity . eta)
现在Compose . Identity . eta 是一种自然转换,但你不能htraverse 使用它,因为你不知道Applicative g。即使您可以这样做,runIdentity 调用也会返回 g (t Identity),而您无法将 g 放回 t 中。
然后我意识到我的htraverse 并不真正类似于普通的旧traverse。 traverse 的遍历函数将新值 inside 放入 Applicative 效果中,使类型表达式变大。所以htraverse 应该是这样的:
class HFunctor t => HTraversable t where
htraverse :: Applicative a => (forall x. f x -> a (g x)) -> t f -> a (t g)
很有希望这个定义看起来更像Traversable,而hmapDefault 会顺利进行,
hmapDefault :: HTraversable t => (forall x. f x -> g x) -> t f -> t g
hmapDefault eta = runIdentity . htraverse (Identity . eta)
但我正在努力为sequenceA 想出一个好的类比。我试过了
hsequence :: (HTraversable t, Applicative f) => t f -> f (t Identity)
hsequence = htraverse (fmap Identity)
但我无法想出以hsequence 来实现htraverse 的方法。和以前一样,f 不是自然转换。
htraverse f = hsequence . hmap f
-- • Couldn't match type ‘x’ with ‘g x’
-- Expected type: f x -> a x
-- Actual type: f x -> a (g x)
我怀疑我的hsequence 类型签名错误。 Applicative 是问题吗 - 我需要一直到 indexed monads 吗? “从Functor 类别到 Hask 的可遍历函子”的类应该是什么样的?这样的事情还存在吗?
【问题讨论】:
-
如果
~>是自然转换箭头,那么sequenceA :: (Applicative f) => t . f ~> f . t可以在更高的上下文中重新解释,所以这就是我要关注的内容。但是,是的,看起来您需要更高的应用程序。 -
有趣!我的常规方法在这里没用。
标签: haskell functional-programming monads category-theory traversable