2017-05-11 8 views
2

文字列の文字が文字か数字か句読記号かどうかをチェックするこの関数があります。そうでない場合はTrueを返します。しかし、私がそれをテストすれば、うまくいきません。ハスケルの文字列を変更する

punct :: Char -> Bool 
punct c | c `elem` ['.', ',', '?', '!', ':', ';', '(', ')'] = True 
     | c isDigit = True 
     | c isAlpha = True 
     | otherwise = False 

この関数は、上記のいずれかの後に空白を追加します。

format :: String -> String 
format s = intercalate "" [if (punct c) then (c:" ") else [c] | c <- s] 

後上記を削除する必要があります。punctでチェックしてください。

format :: String -> String 
format s = map (\c -> if punct c then (c:" ") else [c]) 

しかし、それは、任意の提案を働いていない: は、実は私はこのような何かをしようとしたスペース と直接PUNCTからのものに置き換えることができると思いますか?私はマップとフィルタを使うことができると思いますか?私が間違っている?

+0

「*上記のものを削除する」とはどういう意味ですか?句読点? –

+0

@Willem Van Onsem:句読点で真を返す記号 – Madalina

+1

「それは機能していません」と言ったら、何を意味するのかを明記してください。このコードはコンパイルされないので、「コンパイルできません」と言ってエラーメッセージを出してください。 –

答えて

2

それはあなたのmapString S(そう[Char] S)にChar Sをマップするためない作業がある理由。その結果、mapの出力は[String]になります。ただし、の場合は、上記のを削除すると、マップ内の関数は文字を削除しません。

さらにpunct機能が正しくありません。 isDigitなどは関数です。だからないc isDigitisDigit cでそれを呼び出す:

punct :: Char -> Bool 
punct c | c `elem` ['.', ',', '?', '!', ':', ';', '(', ')'] = True 
     | isDigit c = True 
     | isAlpha c = True 
     | otherwise = False

にもかかわらず、あなたは簡単にこの文をよりコンパクトにし、にそれを変換することができます:

punct :: Char -> Bool 
punct c = isDigit c || isDigit c || c `elem` ['.', ',', '?', '!', ':', ';', '(', ')']

二つの選択肢がここにあります:(1)あなたのいずれかが、 後処理を実行して、すべての句読点を除外します。または(2)句読点を削除する場合は、の代わりにの置換の代わりにを挿入します。

(1)ポスト処理

後処理は、単にfilter次のとおりです。

post_format :: String -> String 
post_format = filter (not . punct) 

あなたはより良い利用後処理、あなたはまだ "オリジナル" を使用したい場合format機能。

helper :: Char -> Char 
helper x | punct x = ' ' 
     | otherwise = x 

その後format崩壊:あなたはhelper機能を使用することができ、その場合には

(1)交換

format :: String -> String 
format = map helper 
+1

ありがとうございます。私はシンタックスをよく知らないので、私がwrog punctを定義したことを知らなかった。もう一度たくさんありがとう – Madalina

1

さて、このコードは」勝ちましたtコンパイルします。

まず第一に、あなたのpunct機能では、このコンパイルエラーが二度起こる:それは一度に一つの問題をコンパイルしない理由のタックルしてみましょう

Foo.hs:7:11: error: 
    • Couldn't match expected type ‘(Char -> Bool) -> Bool’ 
        with actual type ‘Char’ 
    • The function ‘c’ is applied to one argument, 
     but its type ‘Char’ has none 
     In the expression: c isDigit 
     In a stmt of a pattern guard for 
        an equation for ‘punct’: 
     c isDigit 
コンパイラはここであなたを伝えようとしていることということです何

あなたは明らかに別の方法を意味していたときに、 "isDigit"という引数を渡して "関数としてcを呼び出します"と書いた。だから、最初に我々はそれらを交換:固定それと

punct :: Char -> Bool 
punct c | c `elem` ['.', ',', '?', '!', ':', ';', '(', ')'] = True 
     | isDigit c = True 
     | isAlpha c = True 
     | otherwise = False 

、実際にあなたの最初のformat関数がコンパイルされます。

format1 :: String -> String 
format1 s = intercalate "" [if (punct c) then (c:" ") else [c] | c <- s] 

そしてまた、宣伝として動作しているようです:

*Foo> format1 "a.b_c" 
"a . b _c " 

さて、今度はその第二のformatの機能はどうですか?まあ、最初はそれがコンパイルされません。

Foo.hs:18:12: error: 
    • Couldn't match type ‘[Char] -> [[Char]]’ with ‘[Char]’ 
     Expected type: String 
     Actual type: [Char] -> [[Char]] 
    • Probable cause: ‘map’ is applied to too few arguments 
     In the expression: map (\ c -> if punct c then (c : " ") else [c]) 
     In an equation for ‘format’: 
      format s = map (\ c -> if punct c then (c : " ") else [c]) 

をコンパイラを使用すると、右側にsを使うのを忘れていました(「考えられる原因」メッセージで)ここに、あなたを語っている、と書かれている必要があります。

format s = map (\c -> if punct c then (c:" ") else [c]) s 

しかし、コンパイルされませんイベント:あなたの結果はStringされているべきであると言っている(ただし、エラーメッセージが今異なっている)

Foo.hs:18:12: error: 
    • Couldn't match type ‘[Char]’ with ‘Char’ 
     Expected type: String 
     Actual type: [[Char]] 
    • In the expression: 
     map (\ c -> if punct c then (c : " ") else [c]) s 
     In an equation for ‘format’: 
      format s = map (\ c -> if punct c then (c : " ") else [c]) s 

(つまり、 Char、または[Char])のリストが、その代わりにはそれがあなたの代わりにの文字に、列に各文字を回したので、これは、[[Char]]

です(String秒のリストでした。この問題を解決する一つの方法文字に各文字を有効にすることです:

format s = map (\c -> if punct c then ' ' else c) s 

もう一つの方法は、単一の文字列に文字列のリストを結合するためにあなたが前に行ったようintercalate ""(またはconcat)を適用することです。

format s = intercalate "" $ map (\c -> if punct c then " " else [c]) s 
+0

説明をありがとう、私は理解し始めた:) – Madalina