Haskell 如何使用foldMap实现遍历

Haskell 如何使用foldMap实现遍历,haskell,typeclass,Haskell,Typeclass,foldMap可通过以下方式实现: foldMap f = getConst . traverse (Const . f) 因此,我的问题是如何实现foldMap遍历: traverse f = ... 或 有一些可折叠的实例无法执行此操作 data Blonk a = Blink | Blank instance Functor Blonk where fmap f Blink = Blink fmap f Blank = Blank instance Foldable

foldMap可通过以下方式实现:

foldMap f = getConst . traverse (Const . f)
因此,我的问题是如何实现foldMap遍历:

traverse f = ...


有一些可折叠的实例无法执行此操作

data Blonk a = Blink | Blank

instance Functor Blonk where
    fmap f Blink = Blink
    fmap f Blank = Blank

instance Foldable Blonk where
    foldMap f _ = mempty
以上是
Blonk
Functor
Foldable
的唯一可能的全面、守法的实现。现在有一条关于可遍历的
的定律:

traverse Identity = Identity
让我们看看它是如何发挥作用的,假设
遍历
是根据
foldMap
实现的,也就是说,有一些术语
g
h
(如果它们愿意,可以提到
f
):

traverse f = g . foldMap h
然后:

请注意,
g mempty
不依赖于
x
,因此必须是
Identity Blink
Identity Blank
,以适合该类型。在前一种情况下

traverse Identity Blank = Identity Blink
                       != Identity Blank
违反了法律。同样地,
traverse-Identity-Blink
是另一案件中违法的证人

(而且,为了证明我没有受到任何打击,有一个守法的
可遍历的
实例:

instance Traversable Blonk where
    traverse f Blink = pure Blink
    traverse f Blank = pure Blank

)Daniel Wagner给出了一个非常好的类型示例,其中包含一个有效的
可遍历的
实例,该实例无法根据其
可折叠的
实例进行定义。但是也有一些类型具有有效的
函子
可折叠的
实例,但它们没有有效的
可遍历的
实例。这样做的主要原因是,
Foldable
实际上没有法律

例如,如果我们愿意,我们可以写作

instance Foldable IO where
  foldMap _ _ = mempty
这样一个实例与其说有用,不如说令人困惑,但它本身并没有什么问题。但是当我们试图编写可遍历IO的实例时会发生什么呢

traverse f m = _1
-- m :: IO a
-- f :: a -> f b
-- _1 :: f (IO b)
好的,所以我们需要做一些类型为
f(iob)
的东西。我们还没有用
f
包装任何东西,所以我们不能用
来制作它;我们只能使用

traverse f m = pure _2
-- m :: IO a
-- f :: a -> f b
-- _2 :: IO b

哦。我们知道如何生成
fb
值,但我们无法生成
b
值。有时,
IO
允许我们使用异常,但是
可遍历的
身份法这次不允许我们使用异常。

这是家庭作业吗?提示:
Foldable=>Traversable
。到目前为止,您取得了什么进展?感谢语义饱和,“闪烁”现在对我来说,这似乎是一个音效,而不是一个合法的英语单词。你是如何从
遍历fx=g(foldMap hx)
遍历fx=g mempty
的?@BenjaminHodgson来自
foldMap
的定义,即
foldMap f=mempty
traverse f m = _1
-- m :: IO a
-- f :: a -> f b
-- _1 :: f (IO b)
traverse f m = pure _2
-- m :: IO a
-- f :: a -> f b
-- _2 :: IO b