2011-06-18 24 views
2

私はhaskell初心者です。私は最後から2番目のリスト要素を返す関数を作成しようとします。ハスケル型数学問題

私はそう開始:

lastButOne :: [a] -> a 
lastButOne list = if null list 
      then 
       0 
      else 
       length list 

0の文字列私はエラーを取得:

Couldn't match type `a' with `Int' 
     `a' is a rigid type variable bound by 
      the type signature for lastButOne :: [a] -> a 

私はそれを理解しています。しかし、私はここで何ができますか?私はリストタイプを知らない。私はここに何を入れることができますか?

ありがとうございます。

+0

あなたが実際に返すようにしたいものを明確ではありません。おそらく意味がありますか? –

+0

@Craig "最後から2番目の要素" – alternative

+0

リストの型である "a"ではなく整数を返すように型シグネチャを作成する – Ankur

答えて

5

0はint型であるため、すべてaで機能しません。私はそうのようなMaybe aを使用する代わりに、お勧めします:

lastButOne :: [a] -> Maybe a 
lastButOne [] = Nothing 
lastButOne [x] = Nothing 
lastButOne xs = Just $ list !! (length xs - 2) 

使用警備員:MonadPlusの任意のインスタンスに対して、一般的には

import Control.Monad (guard) 

lastButOne :: [a] -> Maybe a 
lastButOne list = guard (length list > 1) >> return (list !! (length list - 2)) 

lastButOne :: [a] -> Maybe a 
lastButOne xs | length xs > 1 = Just $ list !! (length list - 2) 
       | otherwise = Nothing 

たぶんのMonadPlusのインスタンスを使用します:

import Control.Monad (guard) 

lastButOne :: MonadPlus m => [a] -> m a 
lastButOne list = guard (length list > 1) >> return (list !! (length list - 2)) 

どこかで、結果をMaybeにしたいとコンパイラに指定する必要があります。通常、これは型が推定されます。これは、Maybeを期待する関数に渡されるためです。

これはO(n)で実行されることに注意してください。おそらくあなたはリストの最後から2番目の要素を見つけたいと思わないでしょう...なぜこれを行う必要がありますか?代わりに配列を使うことを少なくとも考えてください。

+0

@delnan心配していました! - 、機能アプリケーションではありません。 – alternative

+0

はい、心配しないでください。 – delnan

+0

@delnan ghciでテスト済みです。かっこが必要です。 – alternative

4

シグネチャでは、「この関数は任意の型の要素を持つリストを取り、同じ要素の値をリストのすべての要素に返します。一方、コードでは、「この関数は任意の型の要素を持つリストを取り、数値を返します」と述べています。 の正しい型シグネチャはで、[a] -> Int *( "この関数は任意の型の要素を持つリストを取り、Numの型の値を返します")となります。

しかし、リストの長さの代わりに最後から2番目の要素を返すので、型シグネチャは正しいが、コードは正しくありません。あなたはリストからいくつかの項目を取らなければならないか、何とかerrorMaybeの戻り値の型を使用し、パターンmatchignを使用し、それらの場合には句を省略すると、を返します)、最後から2番目要素が2つ未満であるためです。

(*)プレリュードlengthが曲げられていない場合は、パフォーマンスのためにIntsが出るのは(Integral b) => [a] -> bです。

+0

Num bではなく、Integral bでなければなりませんか? – alternative

+0

@monadic:意味がありますが、何らかの理由で 'Data.List.genericLength'は' Num'を使います。私はまだそれを変更し、なぜそれが現在の化身で 'Int'であるのかを書き加えました。 – delnan

3

私はハスケルをも新しくしています。あなたの問題はあなたのコードに0だと思います。私は実際にそれを修正する方法を知っているが、ここに私の解決策ですが、それが参考に願っていません。

lastButOne :: [a] -> a 

lastButOne [] = error "empty list" 
lastButOne [x1] = error "only one element" 
lastButOne [x1,x2] = x1 
lastButOne (x:xs) = lastButOne xs 

左2つの要素があるまで、機能が最初から要素を削除し、これら2つの最初が最後です-しかし、1つ。

1

派手なソリューション

lastButOne :: [a] -> a 
lastButOne [] = error "empty list" 
lastButOne [x] = x 
lastButOne xs = head $ drop 1 $ reverse xs 
+0

'lastButOne = head。ドロップ1。逆は良いです。 – alternative