某人写下这样的foldlM定义需要什么样的知识或培训? [处于保留状态]

问题描述 投票:9回答:3

最近,我试图在我的一些真实案例制作系统中使用Haskell。 Haskell类型系统确实为我提供了很大的帮助。例如,当我意识到我需要一些类型为type的函数时

f :: (Foldable t, Monad m) => ( a-> b -> m b) -> b -> t a -> m b

实际上有foldMfoldlMfoldrM之类的功能。

但是,真正令我震惊的是这些功能的定义,例如:

foldlM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
foldlM f z0 xs = foldr f' return xs z0
  where f' x k z = f z x >>= k

所以功能f'必须是类型:

f' :: a -> b -> b

根据foldr的要求,然后b必须为*-> m *类型,因此foldlM的整个定义可能是有意义的。

另一个示例包括liftA2<*>的定义

(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 id

liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x = (<*>) (fmap f x)

在查看源代码之前,我尝试了一些自己的解决方案。但是差距是如此之大,以至于我以后再写多少行代码都无法提出这种解决方案。

因此,我的问题是,在如此高度抽象的水平上进行推理的人需要哪种知识或特定的数学分支。

[我知道类别理论可能会提供一些帮助,并且我一直关注this great lecture很长时间了,但仍在研究之中。

最近,我试图在我的一些真实案例制作系统中使用Haskell。 Haskell类型系统确实为我提供了很大的帮助。例如,当我意识到我需要某种类型为f :: ...

haskell higher-order-functions fold
3个回答
4
投票

所以理解它的最好方法就是这样做。下面是使用foldlM而不是foldlfoldr实现。这是一个很好的练习,请尝试一下,然后再提出我建议的解决方案。该示例说明了我为实现此目标所做的所有推理,这可能与您的不同,并且可能有偏见,因为我已经知道使用函数累加器。


3
投票

您不需要任何数学方面的专门知识即可编写类似foldM的函数。我已经在生产环境中使用Haskell已有4年了,并且我也很难理解foldM的定义。但这主要是因为它写得不好。请,如果您无法理解一些晦涩的代码,请不要将其视为个人过失。这是foldlM]的可读性更高的版本

foldlM
    :: forall t m a b .
       (Foldable t, Monad m)
    => (b -> a -> m b)  -- ^ Monadic action
    -> b                -- ^ Starting accumulator
    -> t a              -- ^ List of values
    -> m b              -- ^ Computation result inside a monad
foldlM f z xs = (foldr step pure xs) z
  where
    step :: a -> (b -> m b) -> b -> m b
    step cur next acc = do
        result <- f acc cur
        next result

此功能仍然不是最简单的功能。主要是因为它具有foldr的非典型用法,其中中间累加器是一个函数。但是您会看到一些使这种定义更易读的可能:


1
投票

一般来说,逻辑等等。但是您也可以通过学习来学习它。 :)随着时间的流逝,您会注意到一些模式,掌握一些技巧。

类似于此foldr,但带有其他参数。有人认为它可以折叠成函数,因此可以通过.id(其中sometimes实际上是<=<<=<)进行组合,

return
© www.soinside.com 2019 - 2024. All rights reserved.