1

文字列のリストを受け取り、結果として最初の 2 つの文字列をタプルとして含むリストを返す Haskell 関数を作成しています。したがって、出力例は次のようになります。

listtuple ["bride", "zilla", "crazy", "women"] = [("bride", "villa")]
listtuple ["basketball", "football"] = [("basketball", "football")]

私が次のようにアプローチすることを考えていた方法:

listtuple :: Eq a => [Str a] -> [(Str a, Str a)]
listtuple xs = [(x,y) | x <- xs !! 0, y <- xs !! 1]

基本的に、リストの最初と2番目のインデックスの要素を選択するだけでよいと考えましたが、エラーが発生しています。ここで何か助けはありますか?

4

3 に答える 3

10

簡単な答えは

listtuple :: [a] -> [(a,a)]
listtuple (x:y:_) = [(x,y)]
listtuple _ = []

リストには常に 1 つのアイテムが含まれるか、まったく含まれないため、Maybeこの目的のために正確にサーバーを使用することをお勧めします。

listtuple2 :: [a] -> Maybe (a,a)
listtuple2 (x:y:_) = Just (x,y)
listtuple2 _ = Nothing
于 2012-10-11T04:57:02.577 に答える
7

あなたがおそらくやりたかったことはこれでした:

listtuple xs =
    let x = xs !! 0
        y = xs !! 1
     in (x, y)

これはあなたが書いたものと同じではないことに注意してください。その理由は、あなたが書いたリスト内包表記が次のように変換されるためです。

do x <- xs !! 0  -- Treat the first  element of xs as a list
   y <- xs !! 1  -- Treat the second element of xs as a list
   return (x, y)

xs !! 0これは問題を示しています: リストではない場合、 andxs !! 1をリストとして 扱っています。xs !! 0は 1 つの要素にすぎないため、xが と等しいことを宣言する場合はxs !! 0、次を使用します。

let x = xs !! 0
 in <some expression that uses x>

リスト内包表記の<-構文は同じことをしません。コンパイラーはリスト内包表記をリストモナドに変換するため、リストモナドがどのように機能するかを理解するまで、リスト内包表記を避けることをお勧めします。

さて、2 番目の問題は、 を使用することです(!!)。のような部分的な関数を避け、(!!)パターン マッチングを使用してこれらの問題を解決することに集中する必要があります。あなたが要求したことを行うための慣用的な方法は、最初の 2 つの要素でパターン マッチを行うことです。

listtuple (x:y:_) = (x, y)

... ただし、要素が 2 つ未満のリストでは失敗します。結果を として保存することでこれを防ぎます。 a は成功した結果をラップし、失敗をMaybe示します。JustNothing

listtuple :: [a] -> Maybe (a, a)
listtuple (x:y:_) = Just (x, y)
listtuple _       = Nothing
于 2012-10-11T05:20:07.167 に答える
1

あなたのコードにはいくつかのエラーが見られますが、コードが機能しない理由について具体的な質問がある場合はお知らせください。

まず、提供された型シグネチャが無効です。もちろん、自分で名前を付けたデータ構造を定義していない限りString、パラメータのないデータ構造です。コンパイラは のインスタンスであることを既に認識しているため、 のリストには、指定した等価制約も必要ありません。Str aStrStringStringEq

第 2 に、where 句の場所 (のように見える) でリスト内包表記構文を使用しています。Haskell はxs !! 0要素をバインドする前に評価を試みることを考慮してくださいx。これはリスト内包表記であるため、xsStrings のリスト (実際には のリスト) であるため、すぐには失敗しない可能性がありますが、xs 内の最初と 2 番目の文字列から引き出された s のCharタプルになってしまいます。Char

必要なものを生成するパターン マッチングを使用した簡単なソリューションを次に示します。

listtuple :: [a] -> [(a, a)]
listtuple (x:y:zs) = [(x, y)]

これは合計関数ではないことに注意してください (つまり、要素が 2 つ未満のリストを渡すとエラーになります)。これは、空のリストまたは 1 つの要素リストが渡されたときに空のリストを返すことで、合計にすることができますが、それは意図した目的で機能しますか?

これは、独自のバージョンを作成するために使用したメンタル モデルに適合する代替バージョンです。

listtuple xs = [(x, y)]
            where
                x = xs !! 0
                y = xs !! 1
于 2012-10-11T04:55:46.823 に答える