-2
入力が"A1CB1"
の場合、出力を[A1, C, B1]
にする方法は?私の入力が「A1CB1」の場合、出力を[A1、C、B1]にする方法は?
data Quest = A1 | B1 | C
getQuest :: String -> Maybe [Quest]
入力が"A1CB1"
の場合、出力を[A1, C, B1]
にする方法は?私の入力が「A1CB1」の場合、出力を[A1、C、B1]にする方法は?
data Quest = A1 | B1 | C
getQuest :: String -> Maybe [Quest]
このようなことがありますか?それはおそらく短い/よりエレガントに行うことができますが、以下のスニペットは、私は願ってアイデアが明らかに:
import Data.List
import Data.Maybe
data Quest = A1 | B1 | C deriving
(Enum -- Defines sequential ordering
, Bounded -- Name the lower and upper limits of a type
, Show -- String conversion
, Read -- Conversion from string
)
-- A parser for "a" is a function that works on input,
-- and then possibly yields a value of type "a", and the
-- remaining input.
type Parser a = String -> (Maybe a, String)
-- Give us all possible quests.
allQuests :: [Quest]
allQuests = [minBound..]
-- Simply lift a value to the "Parser" domain.
yield :: a -> Parser a
yield value = \input -> (Just value, input)
-- A parser that always fails.
decline :: Parser a
decline = \input -> (Nothing, input)
-- Creates a parser for a given Quest.
-- maybe: http://hackage.haskell.org/package/base-4.8.2.0/docs/Prelude.html#v:maybe
-- stripPrefix: http://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:stripPrefix
parseQuest :: Quest -> Parser Quest
parseQuest quest = \input ->
maybe (decline input) -- Default: decline the input
(yield quest) -- If we found the correct prefix: yield it.
(stripPrefix (show quest) input) -- Try to strip the prefix.
-- Parse a string into a list of quests.
-- Defined to be somewhat fault tolerant: the function
-- will attempt to parse as much as it can, and will yield
-- the remaining input in its result.
-- find: http://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:find
--
parseQuests :: Parser [Quest]
parseQuests = \input ->
let parsers = map parseQuest allQuests -- A list of parsers; one for each quest.
results = map ($ input) parsers -- Each parser is applied to "input".
in case find (isJust . fst) results of -- Stop when one parser succeeded.
Nothing -> yield [] input -- No quest could be parsed.
Just (Just quest, rest) ->
let (Just quests, rest') = parseQuests rest -- Parse the rest recursively.
in yield (quest:quests) rest' -- And then yield it all.
これは与える:
parseQuests "A1CB1" == (Just [A1,C,B1],"")
それとも、あなたの関数と同じ何かをしたい場合:
をgetQuest = fromJust . fst . parseQuests
getQuest "A1CB1" == [A1,C,B1]
だから
注:コンストラクタの名前が重複していることを考慮しませんでした。 B12 :: Quest
を追加)。このケースを説明する1つの方法は、結果をから順番に並べて、parseQuests
がの前に解析して、B12
の前に解析しようとしますが、これは必ずしも機能しません。あいまいさがある場合、例えば:
data Quest = C1 | EC1 | E
-- Should input "EC1" be parsed as [E, C1] or [EC1]?
またはだけ特定の組み合わせが正常に解析する:
data Quest = AB | ABC | DE
-- Input "ABCDE" would only parse as [ABC, DE],
-- but will fail when parsing starts with AB.
ところで:与えられたデータであり、例えば、文字列を出力することは不可能である - ない 'B1は存在しません。 :Quest' – Carsten
申し訳ありませんが、A2はB1です –