List &引用;武当;在列表中
我有如下几点:List &引用;武当;在列表中,list,haskell,syntax,list-comprehension,infinite,List,Haskell,Syntax,List Comprehension,Infinite,我有如下几点: [bla z|n<-[0..], let z = foo n, z < 42] [bla z|n对此我没有一个好的答案,所以我只建议一个让您尽可能多地使用列表理解的乱码: map snd . takeWhile fst $ [(z < 42, bla z)|n<-[0..], let z = foo n] map snd.takeWhile fst$ [(zarbitral(F a)其中 任意=F任意 实例显示(a->b)其中 显示功能 道具单
[bla z|n<-[0..], let z = foo n, z < 42]
[bla z|n对此我没有一个好的答案,所以我只建议一个让您尽可能多地使用列表理解的乱码:
map snd . takeWhile fst $
[(z < 42, bla z)|n<-[0..], let z = foo n]
map snd.takeWhile fst$
[(z<42,bla z)|n由于列表理解不允许这样做,我使用单子理解和定义自定义单子进行了一些黑客攻击。其结果是以下工作:
example :: [Int]
example = toList [1000 + n
| n <- fromList [0..]
, _ <- nonStopGuard (n > 1)
, let z = 10*n
, _ <- stopGuard (z < 42) ]
-- Output: [1002,1003,1004]
上面的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
一个普通的守卫从不发出停止的信号。它只提供一个或零个选择
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))
instance arbitral a=>arbitral(F a)其中
任意=F任意
实例显示(a->b)其中
显示功能
道具单光::F Int->Bool
单道具m=
(m>>=返回)==m
prop_monadLeft::Int->(Int->F Int)->Bool
单德尔夫特x f号提案=
(返回x>>=f)==fx
莫纳达索克:F Int->(Int->F Int)->(Int->F Int)->布尔
莫纳达索克m f g提案=
((m>>=f)>>=g)
==
(m>>=(\x->fx>>=g))
运行100000个测试没有发现反例。因此,上面的F
很可能是一个实际的单子。这听起来是一个很好的点,停止使用列表理解,而是学习使用更高阶的列表函数,如中提供的函数
基本上,列表理解只是嵌套使用concatMap::(a->[b])->[a]->[b]
的一种漂亮语法。因此,您最初的理解:
[bla z|n<-[0..], let z = foo n, z < 42]
一旦你把它写成这样,很容易看出这就是你想要的:
map bla (takeWhile (<42) (map foo [0..]))
map bla(takeWhile)(当然,对于列表理解来说,takeWhile
没有语法糖分。但是,如果你使用map
和takeWhile
,它会变成map bla$takeWhile(<42)$map foo[0..]
,我并不认为这是特别不雅的。你可以这样做[bla z|z如果您为它实现任意
,您可能可以使用快速检查来测试F
是否为Monad
。这完全是胡说八道。+1。@icktoofay谢谢,我刚刚尝试了您的建议。100000次测试后没有反例。
[bla z|n<-[0..], let z = foo n, z < 42]
let step n = let z = foo n
in if z < 42 then [] else [bla z]
in concatMap step [0..]
map bla (filter (<42) (map foo [0..]))
map bla (takeWhile (<42) (map foo [0..]))