0

私はこのようなデータ構造を持っています

data Something = Something Integer String String

そして変換したい

["Something", "3", "text", "42"] 

データに。

今のところ、私は持っています

altRead :: Read a => [String] -> a
altRead = read . unwords . hack
    where 
        hack = map (\x -> if isNumber x then x else "\"" ++ x ++ "\"")
        isNumber = foldl (\b c -> isDigit c && b) True 

しかし、一部の数値がデータ構造の文字列になる可能性があることを忘れていました。これに対する簡単な解決策はありますか、それとも代替の読み取り型クラスを書く必要がありますか?

4

3 に答える 3

3

あなたが持っているものでは、それを型クラスにする必要はありません。あなたはただ行うことができます:

readSomething :: [String] -> Maybe Something
readSomething [_, n, s1, s2] = Just $ Something (read n) s1 s2
readSomething _              = Nothing

または、最初の単語のあいまいさを解消したい場合:

data Something = Something Integer String String
               | SomethingToo String Integer

readSomething :: [String] -> Maybe Something
readSomething ["Something", n, s1, s2] = Just $ Something (read n) s1 s2
readSomething ["SomethingToo", s, n]   = Just $ SomethingToo s (read n)
readSomething _                        = Nothing
于 2013-02-07T15:26:29.273 に答える
3

lexed トークンの上に小さなパーサーを書いています。それ以来、Readインスタンスを実際に実装することはできません。ただし、既存のインスタンスを利用して、たとえば、 の解析をブートストラップすることができます。read :: Read a => String -> a[String] -> aa == SomethingReadInteger

それでは、試してみましょう。Somethingトークンのリストからa を解析します。

import Safe -- gives us readMay :: Read a => String -> Maybe a

parseSomething :: [String] -> Maybe Something
parseSomething ("Something":strInt:stra:strb:_) = 
  do int <- readMay strInt
     return $ Something int stra strb
parseSomething _ = Nothing

Maybeとして使用して、もう少しコンパクトにすることもできApplicativeます。

import Control.Applicative

parseSomething :: [String] -> Maybe Something    
parseSomething ("Something":strInt:stra:strb:_) = 
  Something <$> readMay strInt <*> pure stra <*> pure strb
parseSomething _ = Nothing

実際には、解析を続行できるように、未使用のトークンも返す必要があります。

parseSomething :: [String] -> (Maybe Something, [String])
parseSomething ("Something":strInt:stra:strb:rest) = 
  (Something <$> readMay strInt <*> pure stra <*> pure strb, rest)
parseSomething rest = (Nothing, rest)

このすべての構造を解析に持ち込む理由は、これが のようなパーサー コンビネータの空間に向かい始めるからParsecです。複雑なものが必要になったときはいつでもRead、Haskell の非常に優れた構文解析ライブラリーのいくつかを見ると便利になり始めます。

于 2013-02-07T21:55:04.070 に答える
1

GHCI では:

data Something = Something Integer String String deriving (Read, Show)

let somethingStrings = ["Something", "3", "text", "42"]

let escapeForSomething [a,b,c,d] = [a, b, "\""++c++"\"", "\""++d++"\""]

let something = read (unwords (escapeForSomething somethingStrings)) :: Something
于 2013-02-07T16:17:37.500 に答える