2011-08-24 12 views
5

Haskellには、エスケープシーケンスを使用するstring literalsという番号があります。例えば、\n,\t,\NULなどが挙げられる。ハスケル: "\ 0"を " 0"にするには?

私は、文字列リテラルがある場合:他のすべての文字列リテラルのエスケープシーケンスで

"Newline: \n Tab: \t" 

と同じ:私は上記の文字列を変換する関数escape :: String -> Stringを定義しない方法

let s = "Newline: \\n Tab: \\t" 

を。

Quasi QuotingとTemplate Haskellを使用しても問題ありませんが、結果を得るためにそれらを使用する方法はわかりません。すべてのポインタ?


更新:私はちょうど基本ライブラリに含まれているText.ParserCombinators.ReadPモジュールを見つけました。それは私が欲しいことを行うData.CharのreadLitChar :: ReadS Char関数をサポートしていますが、ReadPモジュールの使い方はわかりません。私は以下を試してみました:

escape2 [] = [] 
escape2 xs = case readLitChar xs of 
    [] -> [] 
    [(a, b)] -> a : escape2 b 

これは、ReadPモジュールを使用する正しい方法ではないかもしれません。誰でもいくつかのポインタを提供できますか?

別のアップデート:ありがとうございました。私の最後の機能は以下の通りです。悪くはないと思います。

import Text.ParserCombinators.ReadP 
import Text.Read.Lex 

escape xs 
    | []  <- r = [] 
    | [(a,_)] <- r = a 
    where r = readP_to_S (manyTill lexChar eof) xs 
+0

多分あなたはHaskellの-SRC(http://hackage.haskell.org/を使用することができますが生成さそれはおそらく残念です... 更新:多分( "(" \ "++ s ++" \ "")):: String –

答えて

6

何もする必要はありません。するときは、入力した文字列リテラル

let s = "Newline: \\n Tab: \\t" 

をあなたはそれがあなたが望むものであることを確認することができます。

Prelude> putStrLn s 
Newline: \n Tab: \t 
Prelude> length s 
19 

あなただけ

、あなたが何かを得るでしょう sの値をGHCiのを頼む場合
Prelude> s 
"Newline: \\n Tab: \\t" 

明らかに、あなたの背中の背後にエスケープ書式を設定しており、引用符も表示しています。あなたはshowあなたがオリジナルのバックを取得しない文字列は、あなたの代わりに取得するときに、

Prelude> show s 
"\"Newline: \\\\n Tab: \\\\t\"" 
Prelude> print s 
"Newline: \\n Tab: \\t" 

showが値をシリアル化するためのものですので、これはです:あなたはまだ他の答えを得るでしょうprintshowを呼び出したりした場合元の文字列に解析できる直列化された文字列。 の結果は、実際にはprint sprintputStrLn . showと定義されています)で表示されます。 ghciでちょうどshow sとすると、あなたはもっと見知らぬ答えを得ることができます。ここでは、ghciは、showによってシリアライズされた文字をフォーマットしています。

tl; dr - 常にputStrLnを使用して、文字列の値がghciに含まれているかどうかを確認してください。

編集:私は多分あなたは、実際の制御シーケンスにリテラル値に

Newline: \n Tab: \t 

を変換することに気づきました。これを行う最も簡単な方法は、引用符でそれを固執してreadを使用することが考えられます:

Prelude> let s' = '"' : s ++ "\"" 
Prelude> read s' :: String 
"Newline: \n Tab: \t" 
Prelude> putStrLn (read s') 
Newline: 
Tab: 

編集2readLitCharの使用例は、これはreadLitCharを除いて、クリスの答えに非常に近いです:

strParser :: ReadP String 
strParser = do 
    str <- many (readS_to_P readLitChar) 
    eof 
    return str 

readP_to_Sで実行すると、一致するパーズのリストが表示されます(複数の一致は存在しないはずですが、一致しない可能性があるので、空のリストを確認する必要があります)。

> putStrLn . fst . head $ readP_to_S strParser s 
Newline: 
Tab:  
> 
+0

文字列の前後に引用符を追加して読んで信頼できる? – Snoqual

+0

@Snoqual:完全ではありません。 '' \ '" ''この場合、解析エラーが発生します。引用符にエスケープ文字を追加することもできます(分割パッケージを使用します)。文字列リテラルを使って、各文字列で動作することをテストします –

2

約QQとTHは、コンパイル時にこの変換を実行することを意味します。単純なString - >何かの変換では、GHCのリテラル機能OverloadedStringを使うことができます。

EDIT 2:Text.Read.Lexにさらさ文字レクサーを使用して

module UnEscape where 

import Data.String(IsString(fromString)) 
import Text.ParserCombinators.ReadP as P 
import Text.Read.Lex as L 

newtype UnEscape = UnEscape { unEscape :: String } 

instance IsString UnEscape where 
    fromString rawString = UnEscape lexed 
    where lexer = do s <- P.many L.lexChar 
        eof 
        return s 
      lexed = case P.readP_to_S lexer rawString of 
        ((answer,""):_) -> answer 
        _ -> error ("UnEscape could not process "++show rawString) 

EDIT 1

instance IsString UnEscape where 
    fromString rawString = UnEscape (read (quote rawString)) 
    where quote s = '"' : s ++ ['"'] 
:私は今、GHCの読み取りを使用して、より良いUNESCAPEインスタンスを持っています

例:

module UnEscape where 

import Data.String(IsString(fromString)) 

newtype UnEscape = UnEscape { unEscape :: String } 

instance IsString UnEscape where 
    fromString rawString = UnEscape (transform rawString) 
    where transform [] = [] 
      transform ('\\':x:rest) = replace x : transform rest 
      transform (y:rest) = y : transform rest 
      -- also covers special case of backslash at end 
      replace x = case x of 
         'n' -> '\n' 
         't' -> '\t' 
         unrecognized -> unrecognized 

上記UNESCAPEを使用してモジュールから別のモジュールである必要があります:

{-# LANGUAGE OverloadedStrings #-} 
module Main where 

import UnEscape(UnEscape(unEscape)) 

main = do 
    let s = "Newline: \\n Tab: \\t" 
     t = unEscape "Newline: \\n Tab: \\t" 
    print s 
    putStrLn s 
    print t 
    putStrLn t 

これは

shell prompt$ ghci Main.hs 


GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Loading package ffi-1.0 ... linking ... done. 
[1 of 2] Compiling UnEscape   (UnEscape.hs, interpreted) 
[2 of 2] Compiling Main    (Main.hs, interpreted) 
Ok, modules loaded: Main, UnEscape. 
*Main> main 
"Newline: \\n Tab: \\t" 
Newline: \n Tab: \t 
"Newline: \n Tab: \t" 
Newline: 
Tab: 
+0

こんにちはChris。ありがとう、自分のコードですべてのエスケープシーケンスの解析機能全体を再現する必要がないことを願っていました – Snoqual

+0

私はすぐにシンプルGHCが内部の解析機能を公開している場所ですが、GHCで見つけてコピー/ペーストすることができます。 –

+0

私は、自分自身を実装したりコピーしたりすることで、その機能を再現したくないということを意味しています。 – Snoqual

関連する問題