【问题标题】:What should a "higher order Traversable" class look like?“高阶 Traversable”类应该是什么样的?
【发布时间】: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 gIdentityx 统一时,必须与yg 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 并不真正类似于普通的旧traversetraverse 的遍历函数将新值 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 的可遍历函子”的类应该是什么样的?这样的事情还存在吗?

【问题讨论】:

标签: haskell functional-programming monads category-theory traversable


【解决方案1】:

首先,我们有sequence = traverse id

这里htraverse 的第一个参数的类型为forall x. f x -> a (g x),我们不能有id,但我们可以尝试使用同构。要使f xa (g x) 同构,我们可以选择f ~ Compose a g

htraverse = hsequence . hmap (Compose . eta)

hsequence :: Applicative a => t (Compose a g) -> a (t g)
hsequence = htraverse getCompose

【讨论】:

  • 我认为您的意思是htraverse eta = hsequence . hmap (Compose . eta)hsequence :: Applicative a => t (Compose a g) -> a (t g)?这似乎有效!谢谢!
  • 糟糕,我确实是这个意思。
  • 在这种情况下,我认为这些类型中最优雅的版本是htraverse :: Applicative a => (f ~> Compose a g) -> t f -> a (t g)hsequence :: Applicative a => t (Compose a g) -> a (t g)。那么htraversehsequence的代码与普通Traversable的代码完全相同
猜你喜欢
  • 1970-01-01
  • 2015-03-20
  • 2012-01-05
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 2015-12-09
  • 2017-12-14
相关资源
最近更新 更多