【问题标题】:The composition of functions in a list of functions!函数列表中的函数组成!
【发布时间】:2011-05-19 12:37:54
【问题描述】:

我需要定义一个函数'Compose',它接受一个列表'L',它是一个函数列表。当我指定一个适合列表中所有函数的参数时,最后一个函数使用此参数评估自身。然后将结果传递给倒数第二个函数,依此类推,直到我们到达列表中的第一项(函数)并得到最终结果。

例如

撰写 ( ( fn N -> N + 1 ) ^ ( fn N -> 2 * N ) ^ # ) 3 .

给出答案 7.

我必须用我大学的一位讲师设计的一种称为 SAL(简单应用语言)的函数式编程语言编写此代码(因此上面的语法很有趣(^ 分隔列表项,# 标记列表的结尾)。

如果任何解决方案都可以用伪代码编写,请记住我不能使用循环、变量等,这将不胜感激。显然,解决方案是一个单行的答案。我想它涉及递归(我们 99% 的任务函数都这样做!)。

我也不懂 Haskell(我想我得学习一下!)所以伪代码甚至是简单的英语都会很棒。 ——

非常感谢。

【问题讨论】:

    标签: haskell recursion functional-programming


    【解决方案1】:

    在haskell中:

    compose :: a -> [a -> a] -> a
    compose a (x:xs) = x (compose a xs)
    compose a [] = a
    

    【讨论】:

      【解决方案2】:

      Dan 有点放弃了,但这里有一个关于如何自己做的提示。您可以对数字进行递归:

      0! = 1
      n! = (n-1)! * n
      

      您还可以对结构进行递归。例如,一个列表具有递归结构,分为两种情况:一个空列表,以及一个项目后跟列表的其余部分。没有特定的语言:

      List :=   Item x List 
              | Nil
      

      Item 标记列表的头部,x 是头部存储的值,List 是尾部。在这个语法中,你的列表会写成:

      Item ( fn N -> N + 1 ) Item ( fn N -> 2 * N ) Nil
      

      您教授发明的语法中的列表规则可以递归编写为:

      List :=   x ^ List
              | #
      

      列表上的函数必须在此结构上递归,这意味着它处理两种情况中的每一种:

      sum l:List = Nil -> 0
                 | Item x xs:List = x + sum xs
      

      具体来说,递归是术语sum l:List = x + sum xs。使用教授的语法编写此函数作为练习。

      在您的问题中,您的元函数需要一个函数列表并且必须返回一个函数。考虑每种情况,空列表和一个项目(头部),后跟一个列表(尾部)。在后一种情况下,您可以递归地使用您的函数从尾部获取函数,然后以某种方式将其与头部组合以返回一个函数。无论如何,这就是要点。

      【讨论】:

        【解决方案3】:

        如果解决方案是单行答案,则可能涉及折叠:

        compose :: [a -> a] -> a -> a
        compose fs v = foldl (flip (.)) id fs $ v
        

        http://haskell.org/haskellwiki/Compose

        您也可以将其实现为正确的折叠,按照您想要的方式工作:

        compose = foldr (.) id
        
        *Main> let compose = foldr (.) id
        *Main> compose [\x -> x+1, \x -> 2 * x, id] 3
        7
        

        【讨论】:

        • 在你的第一个版本中,$ 是不必要的,因此你可能想这样写:compose = foldl (flip (.)) id
        • 感谢您的评论,但这并不是我真正的解决方案,而是从我发布的链接中复制的。
        • 如果右折叠具有所需的语义,通常会更好地处理这种特殊的事情——更懒惰和更高效。
        • 11 年后,但 foldr (.) id = foldr1 (.) 等 :)
        【解决方案4】:

        这是我使用的:

        compose :: [a -> a] -> a -> a
        compose list startingvalue = foldl (\x f -> f x) startingvalue list
        

        【讨论】:

          【解决方案5】:

          同样使用幺半群,无点

          import Data.Monoid
          compose :: [a -> a] -> a -> a
          compose = appEndo . mconcat . map Endo
          

          或者更笼统地说:

          import Data.Monoid
          compose :: (Functor t, Foldable t) => t (a -> a) -> a -> a
          compose = appEndo . foldl1 (<>) . fmap Endo
          

          【讨论】:

          • 嗯?为什么不只是compose :: Foldable t =&gt; t (a -&gt; a) -&gt; a -&gt; a; compose = appEndo . foldMap Endo
          • 是的,mconcat = foldl1 (&lt;&gt;) = fold,因此是fold . map Endo == foldMap Endo
          猜你喜欢
          • 2011-07-28
          • 1970-01-01
          • 1970-01-01
          • 2010-12-04
          • 2019-02-23
          • 1970-01-01
          • 2011-05-24
          • 1970-01-01
          • 2010-12-25
          相关资源
          最近更新 更多