Haskell 如何使用foldMap实现遍历
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 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