2017-11-11 12 views
3

私は、テストの準備のためにHaskellで課題を作業中です。現在のタスクでは、次の式の後に文字列をトークン化するかどうかを問い合わせます。 "tokenize str separate remove"を実行すると、文字列のリストを出力する必要があります。文字列 "separate"に現れる "str"のすべての文字は、1文字の文字列でなければなりません。文字列 "remove"に現れる "str"のすべての文字は削除する必要があります。別のものと取り除かれていないものは一緒にまとめてください。ハスケルの再帰的トークナイザ

例は、それが問題を例にその事業者ということで、ある程度まで働く出力

["a", "+", "b", "*", "12", "-", "def"] 

tokenize :: String -> String -> String -> [String] 
tokenize [] _ _ = [] 
tokenize [x] _ _ = [[x]] 
tokenize (x:xs) a b  | x `elem` a = [x] : tokenize xs a b 
         | x `elem` b = tokenize xs a b 
         | otherwise = (x:head rest) : tail rest 
           where 
             rest = tokenize xs a b 

以下の私の現在のコード

tokenize "a + b* 12-def" "+-*" " " 

がすべきことを示していそれに先行する文字と一緒に束ねられています。別の文字列にある事業者にもかかわらず、この

["a+","b*","12-","def"] 

よう

+2

問題は行 '|そうでなければ=(x:head rest): 'head rest'とは無関係に' 'head rest'の' 'x''を頭に置いてください。 – sjakobi

答えて

1

はおそらく[]になるはずですが、が表示されます。tokenize [x] _ _はおそらくあなたが望むものではありません。次に、セパレータと削除リストを呼び出さないでください。Stringそれらはただ[Char]です。 type String = [Char]のように違いはありませんが、同義語の意味は意味の意味を明確にすることであり、Stringを実際にStringに使用していないため、機能には不向きです。さらに、引数をシャッフルしてtokenize seps rems strにすると、カリングが楽になるためです。最後に、[Char]の代わりにData.Setを使用したいと思うかもしれませんが、ここではその質問に近づくために使用しません。

問題自体は| otherwise = (x:head rest) : tail restです。これは、トークンがセパレータであると思われる場合でも、次のトークンに任意の特殊文字を追加します。あなたの場合、例はhead rest = "+"x = 'a'で、あなたは"a+"になるように参加します。あなたはさらに警戒する必要があります。

(また:あなたのインデントを台無しにされています。それは、すべての警備員を通じて見えですのでwhere句は、全体式に特異的に結合することは、そのようなことは明らかだとインデントされなければならない)

tokenize :: [Char] -> [Char] -> String -> [String] 
tokenize _ _ "" = [] 
tokenize seps rems (x:xs) 
    | x `elem` rems      = rest 
    | x `elem` seps      = [x]:rest 
    -- Pattern guard: if rest has a single-char token on top and that token is a sep... 
    | ([sep]:_) <- rest, sep `elem` seps = [x]:rest 
    -- Otherwise, if rest has a token on top (which isn't a sep), grow it 
    | (growing:rest') <- rest   = (x:growing):rest' 
    -- Or else make a new token (when rest = []) 
    | otherwise       = [x]:rest 
    where rest = tokenize xs seps rems 

あなたは可能また使用してくださいfilter

tokenize seps rems = tokenize' . filter (not . flip elem rems) 
    where tokenize' "" = [] 
     tokenize' (x:xs) 
      | x `elem` seps      = [x]:rest 
      | ([sep]:_) <- rest, sep `elem` seps = [x]:rest 
      | (growing:rest') <- rest   = (x:growing):rest' 
      | otherwise       = [x]:rest 
      where rest = tokenize' xs