あなたがおそらくやりたかったことはこれでした:
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
示します。Just
Nothing
listtuple :: [a] -> Maybe (a, a)
listtuple (x:y:_) = Just (x, y)
listtuple _ = Nothing