gpt4 book ai didi

list - "takeWhile"在列表理解中

转载 作者:行者123 更新时间:2023-12-03 05:04:30 25 4
gpt4 key购买 nike

我有类似以下内容:

[bla z|n<-[0..], let z = foo n, z < 42]

问题是,我希望列表理解尽快结束 z < 42失败了,就好像它是一个 takeWhile 一样。我知道我可以将其重构为一堆过滤器和映射,但通过列表理解它会更加优雅。

结合列表推导式和 takeWhile 的最优雅的方式是什么?

最佳答案

由于列表推导不允许这样做,所以我使用 monad 推导并定义了一个自定义 monad。其结果是以下工作:

example :: [Int]
example = toList [1000 + n
| n <- fromList [0..]
, _ <- nonStopGuard (n > 1)
, let z = 10*n
, _ <- stopGuard (z < 42) ]

-- Output: [1002,1003,1004]

上面的工作原理与正常的列表理解相同,但有两种不同类型的防护。一个nonStopGuard除了需要奇怪的语法之外,它可以用作常规防护。一个stopGuard相反,它会做更多的事情:一旦它变为 false,它就会停止考虑之前的生成器(例如 <-[0..] )中的进一步选择。

我写的小库如下所示:

{-# LANGUAGE DeriveFunctor, MonadComprehensions #-}
import Control.Monad
import Control.Applicative

data F a = F [a] Bool
deriving (Functor, Show)

Bool上面是一个停止位,表明我们必须停止考虑进一步的选择。

instance Applicative F where pure = return; (<*>) = ap
instance Monad F where
return x = F [x] False
F [] s >>= _ = F [] s
F (x:xs) sx >>= f = F (ys ++ zs) (sx || sy || sz)
where
F ys sy = f x
F zs sz = if sy then F [] False else F xs sx >>= f

最后if将丢弃 xs部分时f x信号停止。

nonStopGuard :: Bool -> F ()
nonStopGuard True = F [()] False
nonStopGuard False = F [] False

普通 guard 从不示意停止。它只提供一个或零个选择。

stopGuard :: Bool -> F ()
stopGuard True = F [()] False
stopGuard False = F [] True

停止警戒一旦变为错误,就会发出停止信号。

fromList :: [a] -> F a
fromList xs = F xs False

toList :: F a -> [a]
toList (F xs _) = xs

最后一个警告:我不完全确定我的 monad 实例定义了一个实际的 monad,即它是否满足 monad 定律。

<小时/>

根据@icktoofay的建议,我编写了一些快速检查测试:

instance Arbitrary a => Arbitrary (F a) where
arbitrary = F <$> arbitrary <*> arbitrary

instance Show (a -> b) where
show _ = "function"

prop_monadRight :: F Int -> Bool
prop_monadRight m =
(m >>= return) == m

prop_monadLeft :: Int -> (Int -> F Int) -> Bool
prop_monadLeft x f =
(return x >>= f) == f x

prop_monadAssoc :: F Int -> (Int -> F Int) -> (Int -> F Int) -> Bool
prop_monadAssoc m f g =
((m >>= f) >>= g)
==
(m >>= (\x -> f x >>= g))

运行 100000 次测试没有发现反例。所以,上面的F很可能是这样的是一个实际的单子(monad)。

关于list - "takeWhile"在列表理解中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29319771/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com