2012-04-15 3 views
2

У меня есть проект для Uni, чтобы написать компилятор (в Haskell) для простого составленного императивного языка. Одним из требований является печать отладочных операторов при вводе вызова функции, оставление функции и назначение переменных.Haskell - распечатать трассировку после выполнения

печати сообщения при вводе функции легко, я просто использую Debug.trace, например:

functionValue = trace "Entering function" (evaluateFunction functionArguments) 

Тот же процесс применяется при назначении переменных. Я не могу понять, как печатать при возврате из вызова функции и правильно синхронизировать выход с другими выходами. Каждая попытка, которую я сделал до сих пор, привела к тому, что «Выходная функция» была напечатана сразу после «Ввод функции» - мне нужно, чтобы внутренние инструкции отладки функции (назначение и вложенные вызовы функций) печатались до того, как печатается «Выходная функция».

Мои императивные привычки говорят мне, что мне нужен способ принудительно выполнить (functionFunction functionArguments) перед выходом функции отпуска, но это кажется невозможным и неправильным в Haskell.

Пример выходных данных я получить сейчас:

Entering main function... 
Leaving main function... 
Entering fn1 function... 
Leaving fn1 function... 
Assigning value1 to A. 
Assigning value2 to C. 
Entering fn2 function... 
Leaving fn2 function... 
Assigning value3 to B. 
Assigning value4 to C. 

выход Same программы так, как мне нужно, чтобы это выглядело:

Entering main function... 
Entering fn1 function... 
Assigning value1 to A. 
Leaving fn1 function... 
Assigning value2 to C. 
Entering fn2 function... 
Assigning value3 to B. 
Assigning value4 to C. 
Leaving fn2 function... 
Leaving main function... 

Итак, что Haskell идиома 'запустить myFunctionWithTraces затем распечатать MyString?

+4

Поскольку вам необходимо гарантировать, что сообщения печатаются в определенном порядке, вы не должны использовать Debug.Trace. Вместо этого укусите пулю, запустите в IO и используйте 'putStrLn' или аналогичный. – dave4420

+0

Собираетесь ли вы в Haskell? –

ответ

5

Если вы хотите сразу распечатать трассировку, вы можете поднять эту функцию до IO monad и поместить ее между двумя putStr s, например.

trace :: String -> IO() -> IO() 
trace name f = do 
    putStrLn $ "Entering " ++ name 
    f 
    putStrLn $ "Leaving " ++ name 

И потом:

main = trace "main" $ do 
    fn1 
    fn2 

fn1 = trace "fn1" $ do 
    return() 

fn2 = trace "fn2" $ do 
    return() 

Это также может быть сделано исключительно с Writer монады (т.е. не печатать, а просто накапливают отладочную как вы идете). trace будет выглядеть примерно так:

trace :: String -> Writer String() -> Writer String() 
trace name f = do 
    tell $ "Entering " ++ name ++ "\n" 
    f 
    tell $ "Leaving " ++ name ++ "\n" 

и с дополнительным шагом разворачивая отладочный с runWriter или execWriter.

Edit: обобщая trace к IO a не так уж сложно:

trace :: String -> IO a -> IO a 
trace name f = do 
    putStrLn $ "Entering " ++ name 
    ret <- f 
    putStrLn $ "Leaving " ++ name 
    return ret 

main = trace "main" $ do 
    a <- fn1 
    b <- fn2 
    print $ a + b 

fn1 = trace "fn1" $ do 
    return 42 

fn2 = trace "fn2" $ do 
    return 69 
+0

@drodgers: Смотрите мое редактирование. –

+0

У меня это получилось! Благодарю. – drodgers

1

[Код был нечитаемым в комментарии, поэтому я отправил еще один ответ как комментарий к Cat Plus Plus]

Я наконец, ввернул IO-монаду через весь мой код, но это решение не совсем работает - мне нужно получить возвращаемые значения (то есть IO (значение)) из моих функций.

do 
    putStrLn $ "Entering " ++ name 
    f 
    putStrLn $ "Leaving " ++ name 

Вышеприведенный фрагмент вернет IO() (пустая монашка ввода-вывода).Таким образом, я изменил его, чтобы быть:

do 
    putStrLn $ "Entering " ++ name 
    returnVal <- f 
    putStrLn $ "Leaving " ++ name 
    return (returnVal) 

Но теперь это печать:

внутри функциональных действий ... ... ... функции Ввод Оставив функцию

Редактировать: Неправильный вывод получался по моей вине: я случайно поставил result <- fдоputStrLn "Entering...

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