2010-12-03 15 views
5

関数のリストであるリスト 'L'を取る関数 'Compose'を定義する必要があります。リスト内のすべての関数に適合するパラメータを指定すると、最後の関数はこのパラメータを使用してそれ自身を評価します。結果は2番目の最後の関数に渡されます。リストの最初の項目(関数)に到達するまで、最終結果が得られます。関数リストの関数の構成!

など。

Compose((fn N→N + 1)^(fn N→2 * N)^#)3。

が、私は私の大学で講師によって考案されたSAL(簡単な応用的言語)と呼ばれる関数型プログラミング言語(上記したがって、変な構文でこれを記述する必要が答え7.

を与える(^リスト項目と#マークをseperatesリストの終わり))。

擬似コードで記述できる解決策があれば、私はループや変数などを使用することはできません。どうやら解決策は1行の答えです。私はそれが再帰を含むと想像しています(私たちのタスク関数の99%が!)。

また、私はハスケル(私は学ばなくてはならないだろうと思う)を理解していないので、擬似コードや普通の英語ですら大丈夫です。 -

ありがとうございます。 Haskellでは

答えて

3

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

ダンは一種のそれを離れていますが、ここではそれを自分で行う方法についてのヒントです。あなたは数字の上に再帰することができます

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

あなたはまた、構造の上に再帰することができます。たとえば、リストには再帰的な構造があり、空のリストとリストの残りが続くアイテムの2つのケースに分類されます。ない特定の言語で:

List := Item x List 
     | Nil 

Itemがリストの先頭をマークし、xヘッドに格納された値であり、Listは尾です。この文法では、あなたのリストが書かれたことになります。

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

リストのためのルール構文であなたの教授が発明として再帰的に書くことができます。リスト上の関数は、この上で再帰しなければならない

List := x^List 
     | # 

それが2つの場合のそれぞれを処理する手段の構造:

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

再帰は、具体的には、用語sum l:List = x + sum xsあります。エクササイズとして残した教授の構文を使ってこの関数を書く。

あなたの問題では、メタ関数は関数のリストを取り、関数を返す必要があります。各ケース、空のリスト、項目(頭部)、リスト(テール)を考えてみましょう。後者の場合、関数を再帰的に使用してテールから関数を取得し、その関数を頭と組み合わせて関数を返すことができます。とにかくそれは要点です。

14

ソリューションは、1行の答えがある場合は、それが倍に関わるものになることができます:

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 
+0

、$は不要であり、そのため、あなたはそれが好きpointfree書きたいと思うかもしれませんこれは: 'compose = foldl(flip(。))id'です。 – HaskellElephant

+0

コメントをいただきありがとうございますが、これは本当に私の解決策ではありませんでしたが、私が投稿したリンクからコピーしました。 –

+1

適切なセマンティクスを持っていれば、この折りたたみ式の方が一般的にははるかに優れています。 – dfeuer

0

は、ここで私が使用したものです:

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

同じ使用モノイド、pointfreeもう少し一般的に

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 
+2

ハァッか。なぜ単に 'compose :: Foldable t => t(a - > a) - > a - > aではないのですか? compose = appEndo。 foldMap Endo'? – dfeuer

+0

それはさらに良いことを指摘してくれてありがとう! – user1747134