HASKELL GHCI 调试器介绍

Posted Hello编程世界

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HASKELL GHCI 调试器介绍相关的知识,希望对你有一定的参考价值。

Haskell GHCi debugger.

I. HASKELL GHCI DEBUGGER

Even though lazy evaluation makes it difficult to apply traditional procedural debugging techniques to Haskell, GHCi contains a simple imperative-style debugger which can stop a running computation in order to examine the values of variables. However, breakpoints and single-stepping are only available in interpreted modules; compiled code is invisible to the debugger.

:sprint can be used to see lazy evaluation by telling you if a variable has been evaluated.

GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help

Prelude>

Prelude> let x = 1 + 2 :: Int

Prelude>

Prelude> :sprint x

x = _  -- Lazy evaluation; therefore, x has not been computed.

Prelude>

Prelude> x

3 -- A value has been requested for x.

Prelude>

Prelude> :sprint x

x = 3 -- Now Haskell shows a value for x.

Prelude>

A. SAMPLE PROGRAM TO DEBUG

Save the following module as Main.hs to your working directory:

module Main where

import System.IO

import Data.Char(toUpper)

main :: IO ()

main = do 

       inh <- openFile "input.txt" ReadMode

       outh <- openFile "output.txt" WriteMode

       mainloop inh outh

       hClose inh

       hClose outh

mainloop :: Handle -> Handle -> IO ()

mainloop inh outh = 

    do ineof <- hIsEOF inh

       if ineof

           then return ()

           else do inpStr <- hGetLine inh

                        hPutStrLn outh (map toUpper inpStr)

                        mainloop inh outh

Then open GHCi and :load Main.hs as shown below:

Prelude>  :load Main

[1 of 1] Compiling Main             ( Main.hs, interpreted )

Ok, modules loaded: Main.

Prelude>

B. BREAKPOINTS

The GHCi debugger enables dynamic breakpoints and intermediate values observation.

The GHCi debugger provides a way of inspecting code. :b N sets a break point in the loaded module at a specific line. When a breakpoint is set on a particular line, GHCi sets the breakpoint on the leftmost subexpression that begins and ends on that line.

As shown below, breakpoints can be set many different ways. For example, by line; by line and column; by module; by module and line; and by module line and column.

:break line

:break line column

:break module

:break module line

:break module line column

Prelude>  :show breaks

No active breakpoints.

Prelude>

An example of setting a ":break module" breakpoint is shown below:

Prelude>  :break mainloop

Breakpoint 0 activated at Main.hs:(15,1)-(21,35)

Prelude>

As shown above the module mainloop starts on (15,1) line 15 column 1 and ends on (21,36) line 21 column 36.

Prelude>  :show breaks

[0] Main Main.hs:(15,1)-(21,35)

Prelude>

Prelude>  :delete *                      -- To delete all breakpoints at once.

Prelude>

Prelude>  :show breaks

No active breakpoints.

Prelude>    

When stopped at a breakpoint or single-step, GHCi binds the variable _result to the value of the currently active result expression. 

To delete a breakpoint, use the :delete <number> command with the number given in the output from :show breaks.

:list is used to list the source code around the current breakpoint.

:trace  can be used once you have hit a breakpoint, to continue to the next breakpoint, recording the history as you go along.

The following first outputs the message then returns the value of f x.

trace :: String -> a -> a

trace ("calling f with x = " ++ show x) (f x)

The trace function outputs the trace message given as its first argument, before returning the second argument as its result.

:back and :forward allow you to go up and down the list of evaluated expressions and inspect each one.

C. EXAMPLES

As shown below, GHCi uses the flag -fbreak-on-exception to allow you to break into program execution at an arbitrary point.

Prelude>  :set -fbreak-on-exception

Prelude>  

Prelude>  import Debug.Trace

Prelude>

Prelude>  :trace main

Stopped at <exception thrown>

_exception :: e = _

Prelude>

Prelude>  :list

Unable to list source for <exception thrown>

Try :back then :list

Prelude>

Prelude>  :back

Logged breakpoint at Main.hs:19:30-41

_result :: IO String

inh :: Handle

Prelude>

Prelude>  :list

18             then return () 

19             else do inpStr <- hGetLine inh                                  

20                     hPutStrLn outh (map toUpper inpStr) 

Prelude>

Prelude>  :hist

-1  : mainloop (Main.hs:19:30-41)

-2  : mainloop (Main.hs:(17,8)-(21,36))

-3  : mainloop (Main.hs:16:17-26)

-4  : mainloop (Main.hs:(16,5)-(21,36))

-5  : mainloop (Main.hs:(15,1)-(21,36))

-6  : main (Main.hs:10:8-24)

-7  : main (Main.hs:9:16-46)

<end of history>

Prelude>    

II. REFERENCES

Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.

Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.

Goerzen, J. & O'Sullivan, B. &  Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.

Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.

Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.

Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.


以上是关于HASKELL GHCI 调试器介绍的主要内容,如果未能解决你的问题,请参考以下文章

-bash: ghci: 找不到命令(Haskell 交互式 shell,Haskell 安装)

Haskell-ghci,找不到函数toUpper?

Haskell的基本语法和GHCi

Haskell 中 (^) 的奇怪行为

为 Haskell IntelliJ 插件配置 Haskell SDK

Haskell、GHC、win32、开罗