我正在写作业(CIS194 Haskell课程)。
我必须将以下递归函数重写为流水线函数(没有明显的递归)。
fun2 :: Integer -> Integer
fun2 1 = 0
fun2 n
| even n = n + fun2 ( n ‘div‘ 2 )
| otherwise = fun2 (3 * n + 1) 我的第一次尝试是这样的:
fun2''' = sum
. (filter (even))
. unfoldr (\x -> if (even x)
then Just (x, x `div` 2)
else if (x==1) then Nothing
else Just (x, x * 3 + 1))这是一个正常的解决方案,还是很奇怪?
我怎样才能更好地重写fun2?
现在我尝试使用takeWhile和iterate编写版本
第二次尝试:
fun2'' :: Integer -> Integer
fun2'' = sum
. (filter even)
. takeWhile (/=1)
. iterate (\x -> if even x
then x `div` 2
else x * 3 + 1 )我现在对until版本有一点小问题。
发布于 2013-04-22 00:57:01
看起来还不错,这里唯一在Haskell中有点危险的是else if。在这种情况下,它可以很好地以应用风格重写:
{-# LANGUAGE TupleSections #-}
import Control.Applicative
import Control.Monad (guard)
fun2''' = sum
. filter even
. unfoldr ( \x -> fmap (x,) $
x`div`2 <$ guard(even x)
<|> x*3 + 1 <$ guard( x/=1 )
)发布于 2013-04-22 19:12:36
现在可以用multi-way IF编写嵌套的if:
g :: Integer -> Integer
g = sum .
unfoldr (\x->
if | even x -> Just (x, x `div` 2)
| x==1 -> Nothing
| otherwise -> Just (0, x * 3 + 1))或者您可以定义自己的if运算符,
(??) t (c,a) | t = c | otherwise = a
g = sum . unfoldr (\x-> even x ?? (Just (x, x `div` 2) ,
(x==1) ?? (Nothing, Just (0, x * 3 + 1))))与until的功能相同,但融合了sum和filter:
g = fst . until ((==1).snd)
(\(s,n) -> if even n then (s+n,n`div`2) else (s,3*n+1))
. ((,)0)或
g = sum . filter even . f
f :: Integer -> [Integer]
f = (1:) . fst . until ((==1).snd)
(\(s,n) -> if even n then (n:s,n`div`2) else (n:s,3*n+1))
. ((,)[])最后一个函数f显示了给定输入数字的整个Collatz序列。
https://stackoverflow.com/questions/16133540
复制相似问题