2015-06-29 2 views
4

Я пытаюсь перевести пример о монадических парсерах (https://www.cs.nott.ac.uk/~gmh/pearl.pdf) в F #.Комбинаторы парсеров F #

До сих пор у меня есть:

type Parser<'a> = Parser of (string -> ('a*string) list) 

let item : Parser<char> = 
    Parser (fun (s:string) -> 
       match s with 
       | "" -> [] 
       | null -> [] 
       | _ -> (s.Chars(0),s.Substring 1)::[]) 

let sat (pred : (char -> bool)) : Parser<char> = 
    parserWf 
    { 
     let! c = item 
     if pred c then return c 
    } 

let char c : Parser<char> = 
    sat (fun c' -> c'.Equals(c)) 

let rec string (str:string) : Parser<string> = 
    parserWf 
    { 
     if (str.Length > 0) 
     then 
      let! c = char (str.Chars 0) 
      let! cs = string (str.Substring 1) 
      printfn "String: %s" cs 
      return c.ToString() + cs 
     else 
      return "" 
    } 

Если удалить else return "" из метода string, то результат всегда пустой список. В Haskell функции строка объявляется:

string :: String -> Parser String 
string "" = return "" 
string (c:cs) = do {char c; string cs; return (c:cs)} 

и это прекрасно работает. Почему функция F # работает не так, как ожидалось?

+4

Вы должны расширить "не работает". Ошибка типа? Ошибка выполнения? Неверный результат? – chi

+0

«Почему функция F # работает не так, как ожидалось [когда я удаляю' else return "" ']?" Ну ... это многое зависит от того, что вы ожидаете. Возможно, вы должны сказать, что это такое. –

+0

Если я удаляю последние буксирные линии строковой функции (иначе возвращаем ""). Тогда, если я делаю «runParser (строка« привет »)« привет! », В F # я получил пустой список, но в Haskell я получил [(« привет »,«! »)]. – user3535953

ответ

0

My Haskell немного ржавый, но не тот фрагмент, который вы разместили, эквивалентный вашему F # -коду, то есть в Haskell тоже вам нужен базовый регистр для рекурсии (пустая строка)?

Если вы удалите часть else, второй для последнего вызова строки (т. Е. Тот, у которого есть только один символ слева) не получит результата от его рекурсивного вызова (передача «"), поэтому он не вернет действительный результат также. Затем он распространяется «вверх», и вы получите пустой список.

Смежные вопросы