2017-03-10 13 views
1

私は初心者だがHaskellのだと私は下図のように特定の初期の人の給料に昇給を与えることができる機能を作るためにしようとしている:Haskellのリスト内の特定のタプルを更新するにはどうすればよいですか?

*Main> giveRaise 'A' 200 [('A',"Al",1000),('B',"Bob",1500)] 

の答えを与えることになりますこの:これまで

[('A',"Al",1200),('B',"Bob",1500)] 

私のコードは、このですが、私は私がnで初期「G」を高めるためにそれをしようとすると、エラーを取得しておく:

giveRaise :: Char -> Int -> [(Char, String, Int)] -> [(Char, String, Int)] 
giveRaise g n [(g, z, m)] 
= [(g, z, (m + n))] 
+0

@ウィレム・ヴァン・オンセムあなたの助けをありがとう、私は今問題をより良く理解し始めています。しかし、私があなたが示唆しているコードを試してみると、私はまだエラーを取得し続けています: "関数の徹底的なパターンgiveRaise"。私は初心者なので、これがまだ何を意味するのか分かりません。これまでの私の更新されたコードは以下の通りです:giveRaise :: Char - > Int - > [(Char、String、Int)] - > [(Char、String、Int)] giveRaise pa n((pb、z、m):tail ) | pa == pb =(pb、z、m + n):テール |そうでなければ=(pb、z、m):giveRaise pa n tail –

+0

問題は、その人がリストに見つからないときに行うことです。 –

+0

@WillemVanOnsem指定されたタプルのリストでは、変更しているタプルは常にそこにあります。それはまったく役に立ちますか? –

答えて

5

あなたがトンを予定していますoリスト内の任意の要素を変更すると、最悪の場合、ループになります。 の再帰はHaskellでループする方法なので、giveRaiseという1つの節を書くのは奇妙です。再帰を使用している場合、あなたは常に節の2種類があります。

  • ベースケース:私たちは人を見つけ、そして彼らに昇給を与えています。そして
  • a再帰的ケース:私たちは現在、まだその人を見つけていないので、それを探し続けています。

ベースの場合は単純です:

giveRaise pa n ((pb,z,m):tail) | pa == pb = (pb,z,m+n):tail

プロローグでは、と統一が(Erlangで、平等がチェックされている)に行われ頭の中で同じ変数を使用することができます。それはハスケルで許可されていません。 Haskellでは、の警備員| pa == pbなど)を使用して、2人の人物が同じかどうかを判断します。

もう1つのオプションがあります。papbではありません。そう、otherwiseケースでは、再帰を実行し、リストにさらに検索:

       | otherwise = (pb,z,m):giveRaise pa n tail

、または一緒に置く:

giveRaise pa n ((pb,z,m):tail) | pa == pb = (pb,z,m+n):tail 
           | otherwise = (pb,z,m):giveRaise pa n tail

我々は考慮に入れる必要があり、最後の場合は最終的にあります。何私たちがリストの最後に到達し、その人を見つけられなかった場合はどうするのですか?私たちは、単にそれを無視するなど、空のリストを返すことができます。

giveRaise _ _ [] = [] 

または我々はerrorを投げることができます。

giveRaise _ _ [] = error "Could not give a raise." 

だから我々はそれが好きで実装できます。

giveRaise pa n ((pb,z,m):tail) | pa == pb = (pb,z,m+n):tail 
           | otherwise = (pb,z,m):giveRaise pa n tail 
giveRaise _ _ [] = error "Could not give a raise."

は、最後にご注意をこのファンクションはという識別子を持つ最初の人物にのみ賭けをします。その識別子を持つ人がいません。私はしかし、識別子は一意であると仮定しました。

+1

私はそれを試してみると、もしも2人の人が同じ識別子 'pb'を持っていれば、最初の(リスト順で)昇給するだけです。 – epsilonhalbe

+0

@epsilonhalbe:ええ、良い点。私は答えの最後にメモを追加しました。 –

2

「リスト内の1つの要素に何かを行いますが」と同じである他の何かが何かを行い、「リスト内のすべての要素に他の何かをする」要素は、1つあなたがあるとき探していると何もないそれがないとき。言い換えれば、この操作をmapとして構造化することは意味があります。

giveRaise :: Char -> Int -> [(Char, String, Int)] -> [(Char, String, Int)] 
giveRaise x amt = map raise 
    where raise (y, n, salary) 
      | x == y = (y, n, salary + amt) 
      | otherwise = (y, n, salary) 
関連する問題