首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将递归函数重写为流水线函数组合

将递归函数重写为流水线函数组合
EN

Stack Overflow用户
提问于 2013-04-22 00:40:11
回答 2查看 479关注 0票数 3

我正在写作业(CIS194 Haskell课程)。

我必须将以下递归函数重写为流水线函数(没有明显的递归)。

代码语言:javascript
运行
复制
fun2 :: Integer -> Integer
fun2 1 = 0
fun2 n 
    | even n = n + fun2 ( n ‘div‘ 2 )
    | otherwise = fun2 (3 * n + 1) 

我的第一次尝试是这样的:

代码语言:javascript
运行
复制
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

现在我尝试使用takeWhileiterate编写版本

第二次尝试:

代码语言:javascript
运行
复制
fun2'' :: Integer -> Integer
fun2'' = sum 
         . (filter even) 
         . takeWhile (/=1) 
         . iterate (\x -> if even x 
                          then x `div` 2
                          else x * 3 + 1 )

我现在对until版本有一点小问题。

EN

回答 2

Stack Overflow用户

发布于 2013-04-22 00:57:01

看起来还不错,这里唯一在Haskell中有点危险的是else if。在这种情况下,它可以很好地以应用风格重写:

代码语言:javascript
运行
复制
{-# 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 )
             )
票数 2
EN

Stack Overflow用户

发布于 2013-04-22 19:12:36

现在可以用multi-way IF编写嵌套的if

代码语言:javascript
运行
复制
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运算符,

代码语言:javascript
运行
复制
(??) 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的功能相同,但融合了sumfilter

代码语言:javascript
运行
复制
g = fst . until ((==1).snd) 
            (\(s,n) -> if even n then (s+n,n`div`2) else (s,3*n+1)) 
    . ((,)0)

代码语言:javascript
运行
复制
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序列。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16133540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档