6

この関数を書くのに助けが得られるかどうか疑問に思います。リスト内の各「ペア」を反転する関数を作成しようとしています。

module Invert where
invert :: [(a,b)] -> [(b,a)]
invert [(a,b)] = [(b,a)]

私が入るときinvert [(3,1) (4,1) (5,1)]...それは私に与えることになってい[(1,3) (1,4) (1,5)ます...しかしそれは私に与えます...


*Invert> [(3,1) (4,1) (5,1)]

<interactive>:2:2:
    The function `(3, 1)' is applied to two arguments,
    but its type `(t0, t1)' has none
    In the expression: (3, 1) (4, 1) (5, 1)
    In the expression: [(3, 1) (4, 1) (5, 1)]
    In an equation for `it': it = [(3, 1) (4, 1) (5, 1)]
4

3 に答える 3

17

リストは再帰的なデータ構造であるため、すべての要素を交換するためにリストを再帰的に処理するか、処理を行う高階関数を使用する必要があります。定義する場合

invert [(a,b)] = [(b,a)]

単一要素リストのみを変換し、他のすべての入力はエラーで失敗します!

入力が取得することを考えてみてくださいinvert。それは空のリストか、空でないリストのいずれかです。空でないリストの場合、最初の要素を交換し、残りを再帰的に変換できます。

invert(自分を反転させたくない場合は、

invert = map swap

swapからですData.Tuple。)

于 2013-02-11T17:18:38.073 に答える
5

したがって、タイプがのリストに関数をマップする必要があります(a, b) -> (b, a)。関数の(,)タイプはb -> a -> (b,a)です。したがって、それを裏返すと、が得られa -> b -> (b, a)ます。今、それをアンカリーすると、次のようになります(a, b) -> (b, a)

 invert = map (uncurry $ flip (,))

例えば

 > map (uncurry $ flip (,)) [(1, "a"), (2, "b")]
 [("a",1),("b",2)]

余談ですが、パッテンのマッチングはあなたが望むものと一致しません。定義

invert [(a,b)] = [(b,a)]

「リストを単一のタプルと一致させる」と言います。複数のタプルを持つリストがある場合、一致は失敗します。また、Josh Leeが指摘したように、リスト内のタプルの間にコンマが必要です。

于 2013-02-11T17:14:33.330 に答える
4

これを解決する最良の方法:それをより小さな問題に分割し、それらを解決するライブラリ関数を見つけるか、独自に作成します。invert次の3つのことを学ぶ必要があるため、これは一部のような関数を作成するよりも優れた演習であると常に初心者に伝えます。

  1. 問題を小さくて再利用可能な部分に分割する方法。
  2. 言語によって提供される標準ライブラリ関数。
  3. 再帰を使用して、標準ライブラリにあるような小さくて再利用可能な関数を作成する方法。

この場合、問題を次のように分割できます。

  1. 個々のタプルを反転します。
  2. リストのすべての要素に関数を適用し、結果のリストを収集します。

2つ目はmap、標準ライブラリに付属しているリストの一般的な関数です。あなたはそれのあなた自身のバージョンを書いてみることができます。この種のことは、初心者にとって常に良い練習です。

map :: (a -> b) -> [a] -> [b]
map f []     = ...
map f (x:xs) = ...

1つ目は、Petrが指摘しているように、からのswap関数ですData.Tuple。しかし、私たちは簡単に自分自身を書くことができます:

swap :: (a, b) -> (b, a)
swap (a, b) = (b, a)

そして今、もちろん:

invert :: [(a, b)] -> [(b, a)]
invert = map swap
于 2013-02-11T19:21:59.733 に答える