2016-10-04 8 views
4

おはようございます、私はhaskellを初めて使っています。私は、文字列のUnicode値を読み込んでリストに格納し、整数を合計するリストを要約しようとしています。「Exception:Prelude.head:empty list」を避けるには? - Haskell

getLetterUnicodeValue :: Char -> Int 
getLetterUnicodeValue l = (ord l) - 64 

unicodeValueList :: String -> [Int] 
unicodeValueList x = getLetterUnicodeValue (head x) : unicodeValueList (tail x) 

total :: [Int] -> Int 
total []  = 0 
total x = (head x) + (total (tail x)) 

文字列が最後の文字になり、合計機能が正常に実行されないと、空のリストのエラーが発生しました。終わりになると機能を停止する方法はありますか?unicodeValueList

*** Exception: Prelude.head: empty list 
+7

はい、あります。あなたは既に 'total' *のためにそれを行っています。... – immibis

答えて

5

この例外を回避する最も確実な方法は、headを使用しないことです。代わりに、リストの先頭と末尾を取得するためにパターンマッチングを使用することができます。

unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs 

total (x:xs) = x + total xs 

こうxxsは、リストが空でないと、あなたが誤って頭にアクセスしないことが保証されている場合にのみ使用可能になりますまたは空のリストの末尾。

もちろん、パターンの一致が不完全であるという警告が表示されます。リストが空の場合に何が起こるべきかを指定しません。もちろんこれは前にも当てはまりましたが、コンパイラが実際にこれを見ることができるようになりました(以前のコードは事前の警告なしに実行時にクラッシュしましたが)。

リストが空の場合はどうすればよいですか?空の文字列にはUnicode値は含まれていません。だから、入力が空であるとき、それは空のリストを返す必要があります:もちろん

unicodeValueList [] = [] 

をあなたははあなたのエラーを修正するためにマッチングパターンを必要としません。 ifを使用して、リストが空でないときにheadtailだけを呼び出すことができます。しかし、そうした場合、コンパイラはチェックが順番どおりであることを確認することができません。パターンマッチングを使用して、安全でないheadtailの機能を完全に回避すると、空のリストの頭や尾に誤ってアクセスすることはなくなり、リストが空であると考えるのを忘れてしまったら警告が表示されます。

2

うん、あなただけの、これはunicodeValueList = map getLetterUnicodeValueとして、よりきれいに書くことができunicodeValueList

unicodeValueList :: String -> [Int] 
unicodeValueList [] = [] 
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs 

ノートにパターンマッチする必要があります。 headのエラーが発生する理由は、再帰には基本的なケースがなく、空のリストに達しても再帰しようとします。

+0

ありがとう、ありがとう! –

関連する問題