3

初めてのポスターですが、このサイトは私を大いに助けてくれました。

Haskellを学ぼうとしています。

これは私が答えるように求められている質問です。

長さのペアのリスト(長さ> = 2)を取り、リストの2番目の要素の最初のコンポーネントを返す関数を記述します。したがって、[(5、'b')、(1、'c')、(6、'a')]を指定すると、1が返されます。

私はこれを自分で行いました。

listtwo :: [([a],b)] -> [a]
listtwo [] = []
listtwo [(a,b)] = fst (head (tail [(a,b)]))

信じているリストタプルのリストを取得して、リストの2番目の項目から1番目の要素を返そうとしています。[(a、b)]を取り出して、2番目の[(a、b)]を、問題のリストのようなリストに置き換えれば、問題なく機能することはわかっています。しかし、この関数をタプルの任意のリストで機能させようとすると。エラーが発生します。

受け取ったエラー

<interactive>:1:27:
No instance for (Num [a0])
arising from the literal `6'
Possible fix: add an instance declaration for (Num [a0])
In the expression: 6
In the expression: (6, 'a')
In the first argument of `listtwo', namely
  `[(5, 'b'), (1, 'c'), (6, 'a')]'

だから私は誰かが私がエラーを解読し、マバイが私が間違っていることを説明するのを手伝ってくれるかどうか尋ねています(私に答えを与えないでください、そのように学ぶことはできません)。

ヘルプを利用してください。これが回答された場合は、さらに質問がある可能性があります。事前にどうもありがとうございました!

4

1 に答える 1

10

リストの2 番目の要素の最初のコンポーネントを返す関数が必要だとします。この関数を記述する最良の方法は、パターン マッチングです。しかし、まず、そのタイプについて考えてみましょう。

のタプルのリストが必要だとします(Int,Char)。と書かれてい[(Int,Char)]ます。任意の型の 2 タプルのリストが必要な場合は、型IntCharを型変数に置き換えるため、 type になります[(a,b)]

関数は、このタイプの何かを取り、リストの 2 番目の要素の最初のコンポーネントを返す必要があります。タプルの最初のコンポーネントはすべて typeaであるため、戻り値の型aも同様でなければなりません。したがって、関数の型シグネチャは

f :: [(a,b)] -> a

では、この関数をどのように記述すればよいでしょうか。最良の方法は、パターン マッチングを使用することです。これは、アクセサー (オブジェクト指向のバックグラウンドを持っている場合はゲッター) を使用せずにデータ構造のコンポーネントを抽出するための優れた方法です。g :: [a] -> aリストの 3 番目のコンポーネントを返す関数があるとします。あなたは書くことができます

g :: [a] -> a
g xs = head (tail (tail xs))

しかし、それはかなり厄介に見えます。もう 1 つの方法は、パターン マッチです。3 つの要素を持つリストは、whereを[x,y,z]実行することで作成できます。これらはすべて型です(演算子は項目をリストの先頭に追加することに注意してください)。したがって、次のように記述できます。x : y : z : []xyza:

g :: [a] -> a
g (x : y : z : []) = z

しかし、これには問題があります。これは、長さ 3 のリストでしか機能しません。なぜなら、私たちのパターンは「3 つの要素のリストを最後に追加された空のリストと一致させる」と言っているからです。代わりに、リストの残りの部分と一致するpatternx : y : z : restを使用できます。rest

g :: [a] -> a
g (x : y : z : rest) = z

ここで、パターンは「3 つの要素のリストに一致し、その後に他の要素がすべて続く」と述べています。実際、もっと簡単にすることができます。値は使用しないxのでy、 Haskell パターン(アンダースコア)restに置き換えることができます。_これは何にでも一致し、その値を使用しないことを約束します。

g :: [a] -> a
g (_ : _ : z : _) = z

これをどのように使用して問題を解決できますか? パターンに一致するリストがあれば、(w,x) : (y,z) : restを返しyます。したがって、次のように書くことができます。

f :: [(a,b)] -> a
f ( (w,x) : (y,z) : rest ) = y

これはうまくいきます。ただし、最初のペアはまったく気にしないので、 に置き換えることができ(w,x)ます_。また、2 番目のタプルの 2 番目の要素またはリストの残りの部分も気にしないので、それらを次のように置き換えることもできます_

f :: [(a,b)] -> a
f ( _ : (y,_) : _) = y

ghci で確認する:

ghci> f [(5,'b'),(1,'c'),(6,'a')]
1

したがって、期待どおりに動作します。

于 2012-06-11T18:45:55.473 に答える