4

私は、オンラインブック「Learn you a Haskell」でHaskellを少し学びたいと思っています。高次関数についての質問があります。Haskellの(高次)関数とのパターンマッチング

私はsome examplesを見て、私はいくつかのより高度な機能をしたいが、私は常に次の例外読んで、なぜ私は知りません:*** Exceptionを

を:euler13.hs:(11,0 ) - (15,39):関数内 非網羅的なパターンが

そして、私は定義された関数を適用するが、これは1です:

apply :: (Num b, Ord b) => (a -> a) -> b -> [a] -> [a] 
apply f n [] = [] 
apply f n [x] 
    | n <= 1 = map f [x] 
    | otherwise = apply f (n-1) (map f [x]) 

私がしたいですpply 'n'は 'f'という具象的な関数をリスト '[x]'に付けます。私はこの関数を多態的にして、paramの型が 'a'になるようにしようとしました。しかし、数値とリストも使用したいので、直接リストを使用しています(数字だけの関数を使用したい場合は、明らかに[数値]になります)

誰かが私を助けてくれますか?私はこの言語が大好きですが、JavaやCと大きく異なるため学習しているときに少し難しいです(たとえば)

ありがとう!

+0

これは、問題のタイトルの名前を変更することをお勧めします。これは、パターンマッチングの問題であり、必ずしも高次関数である必要はありません。 –

+0

OKです。それは今ですか?ありがとう! – albertoblaz

答えて

13

xを中心に[]を削除します。それ以外の場合、2番目のパターンは1つの要素のみのリストと一致することができます。

apply f n x 
    | n <= 1 = map f x 
    | otherwise = apply f (n-1) (map f x) 
+8

そして私たちがそれをしている間、それを「xs」という名前に変更します。これは「何のリスト」のより一般的な名前です。 – delnan

+0

ええ、それは本当です。問題は、私は多くの変更や変更を加えて何もしないことを試みていたことです。しかし、正しいことは 'xs'を使用することです – albertoblaz

5

次の2つのケースについてapplyを定義:nと、空のリストとnと一つの要素のリスト。リストに複数の要素が含まれているとどうなりますか?それは欠けているパターンです。

11

これは他の人の言われたことと変わりませんが、ポイントは苦労するべきでしょうか?リストには2つの基本的な 'コンストラクタ'があります。したがって、リストから関数を定義する際に考慮する必要がある2つの基本的なケース:[](:)の引数。後者の(:)は、そのような種類のリストを持つものに参加することができます。したがって、1[] - 1:[]または[1]です。それとも、11:(1:[])のようなもの、つまり1:[1]、すなわち[1,1]という特別な構文を使用して書くことができます。

data List a = Nil | Cons a (List a) deriving (Show, Eq, Ord) 

[]x:xsの使用は、このような何かのためだけスワンク糖である

あなた自身が、書き込みがリストを定義していた場合は間違っていただろうかより明らかであろう。同様に、特別なString砂糖は['a','b','c']ではなく​​と書くことができます。これは'a':'b':'c':[]よりも優れています。 (上記の定義では、短い文字列の場合は少し多いですが、ByteStringTextの表現を多くの目的で使用する理由がありますが、Cons 'a' (Cons 'b' (Cons 'c' Nil)))と書く必要があります。)このような、より詳細なリストの定義では、我々は我々自身map(というかfmap)、私たちはこのような場合のためにfmapを定義する際に、私は、コンストラクタの両方のタイプを考慮しなければならなかったこと

instance Functor List where 
    fmap f Nil = Nil 
    fmap f (Cons first rest) = Cons (f first) (fmap f rest) 

お知らせを言うことができる追加する必要があります私のリストタイプの場合は、NilCons first rest(またはCons x xsと書かれていることが多い)。

それともあなたはLYAHでFunctor型クラスの一般的な議論にまで持っていない - その場合には、ちょうど、あなたはどのような場合には、独自のmap

として
listMap f Nil = Nil 
listMap f (Cons first rest) = Cons (f first) (listMap f rest) 

を定義することができることを考えますリスト型のこの脱糖書き換え与え、あなたの実際の関数の定義は次のようになります。あなたがカバーしている

apply :: (Num b, Ord b) => (a -> a) -> b -> List a -> List a 
apply f n Nil = Nil 
apply f n (Cons first Nil) 
    | n <= 1 = fmap f (Cons first Nil) -- or listMap f (Cons first Nil) 
    | otherwise = apply f (n-1) (fmap f (Cons first Nil)) 

例は以下のとおりです。

apply f n Nil 
apply f n (Cons first Nil) 

Cons first Nilは、first : []または[first]と同じです(つまり、[x])。しかし、これはあなたがすべてのケースをカバーしていないことを意味し、あなたの定義は「徹底的でない」ことです。複数のメンバーがある場合は、fnをリストに適用する方法については言及していません。リストの形式がNil(最初の行)またはCons x Nil(2行目)ではなく、Cons x (Cons y Nil)またはCons x (Cons y (Cons z Nil))の場合はどうなりますか?

ソリューションは、他の人が言ったようである、または当社の脱糖リスト型を使用して:

apply :: (Num b, Ord b) => (a -> a) -> b -> List a -> List a 
apply f n Nil = Nil 
apply f n (Cons first rest) 
    | n <= 1 = fmap f (Cons first rest) 
    | otherwise = apply f (n-1) (fmap f (Cons first rest)) 

ここで「変数」のrestNilかどうか、すべてのリストをカバーしています。また

*Main> apply (+1) 3 Nil 
Nil 
*Main> apply (+1) 3 (Cons 3 Nil) 
Cons 6 Nil 

あなたと同じように、しかし:したがって、私たちが得る

*Main> apply (+1) 3 (Cons 0 (Cons 1 (Cons 2 Nil))) 
Cons 3 (Cons 4 (Cons 5 Nil)) 
+0

本当に印象的なすべての答え。私に説明してくれてありがとう。はい、私はLYAHでこの部分を起こしていません。私が理解できなかった唯一の理由は、あなた自身の "マップ"機能を定義した理由と、なぜ[]というよりもNilとConsを使ったのですか? sytantic sugarは使いやすいと思う。とにかく、あなたの答えをありがとう! – albertoblaz

2

これは、与えられた他の人に比べて、新しい答えではありませんが、うまくいけば、それにもかかわらず、洞察力です。

すでに関数定義のパターンマッチングについて理解していますが、最初のパターンが一致しなかった場合、評価は次のパターンに進みます。一致しないパターンは、「再現可能」とみなされます。

一般的に、最後の関数定義を「反駁可能」にするとよいでしょう。つまり、常に一致します。 Haskell 2010 reportから次のよう

反駁できないパターンである:NはnewtypeのとAPATによって定義されるコンストラクタである変数、ワイルドカード、N APATはAPATは反論できない、またはフォームである反駁、VARする@ APATあります〜apat。その他のパタ​​ーンはすべて再現可能です。

あなたの誤解は、あなたがそれを反駁パターン(つまり単一の要素にxを結合する単一要素のリスト、ためのパターン)が実際にあるとき[x]は、変数(反駁できないパターン)であると思ったことでした。

長さ3のリストでしか機能しない関数を書いたとします。「網羅的ではないパターン」よりもわかりやすいエラーメッセージが必要な場合は、ワイルドカード(アンダースコア)の反駁可能なパターンを使用できます。わかりやすい例:

sum3 [x,y,z] = x+y+z 
sum3 _  = error "sum3 only works on lists of length 3" 
+0

ああ、それを知ってよかった。実際に私はこの言語を大学ではなく私の自由な時間に学んでいますので、まだハスケルについてはまだ分かりませんが、上記のようないくつかのテクニックと "ハック"を学ぶのは良いことです。 – albertoblaz