summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorPepe Iborra <mnislaih@gmail.com>2007-04-26 09:37:19 +0000
committerPepe Iborra <mnislaih@gmail.com>2007-04-26 09:37:19 +0000
commit45b04f650e6985c524301112a8381a1aff808fc6 (patch)
tree34e210f415393056f8b1ef4b7dfae768d7cf9487 /docs
parenta4a6817fc78562170d00852595cf6af3fa38d209 (diff)
downloadhaskell-45b04f650e6985c524301112a8381a1aff808fc6.tar.gz
New section on debugging lambdas in the ghci user guide
Diffstat (limited to 'docs')
-rw-r--r--docs/users_guide/ghci.xml124
1 files changed, 105 insertions, 19 deletions
diff --git a/docs/users_guide/ghci.xml b/docs/users_guide/ghci.xml
index 61aa5132f9..54ce6b7c74 100644
--- a/docs/users_guide/ghci.xml
+++ b/docs/users_guide/ghci.xml
@@ -1831,22 +1831,90 @@ x :: Int
</varlistentry>
</variablelist></para>
</sect2>
- <sect2><title>Limitations</title>
- <para>
- <itemizedlist>
- <listitem><para>
- Implicit parameters (see <xref linkend="implicit-parameters"/>) are only available
- at the scope of a breakpoint if there is a explicit type signature.
- </para></listitem>
- </itemizedlist>
- <itemizedlist>
- <listitem><para>
- Modules compiled by GHCi under the <literal>-fdebugging
- </literal> flag will perform slower: the debugging mode introduces some overhead.
- Modules compiled to object code by ghc are not affected.
- </para></listitem>
- </itemizedlist>
- </para>
+ <sect2><title>Debugging Higher-Order functions</title>
+ It is possible to use the debugger to examine lambdas.
+ When we are at a breakpoint and a lambda is in scope, the debugger cannot show
+ you the source code that constitutes it; however, it is possible to get some
+ information by applying it to some arguments and observing the result.
+
+ The process is slightly complicated when the binding is polymorphic.
+ We will use a example to show the process.
+ To keep it simple, we will use the well known <literal>map</literal> function:
+ <programlisting>
+import Prelude hiding (map)
+
+map :: (a->b) -> a -> b
+map f [] = []
+map f (x:xs) = f x : map f xs
+ </programlisting>
+ We set a breakpoint on <literal>map</literal>, and call it.
+ <programlisting>
+*Main> :break map
+Breakpoint 0 activated at map.hs:(4,0)-(5,12)
+*Main> map Just [1..5]
+Stopped at map.hs:(4,0)-(5,12)
+_result :: [b]
+x :: a
+f :: a -> b
+xs :: [a]
+ </programlisting>
+ GHCi tells us that, among other bindings, <literal>f</literal> is in scope.
+ However, its type is not fully known yet,
+ and thus it is not possible to apply it yet to any
+ arguments. Nevertheless, observe that the type of its first argument is the
+ same as the type of <literal>x</literal>, and its result type is the
+ same as the type of <literal>_result</literal>.
+ The debugger has some intelligence built-in to update the type of
+ <literal>f</literal> whenever the types of <literal>x</literal> or
+ <literal>_result</literal> are reconstructed. So what we do in this scenario is
+ force <literal>x</literal> a bit, in order to recover both its type
+ and the argument part of <literal>f</literal>.
+ <programlisting>
+*Main> seq x ()
+*Main> :print x
+x = 1
+ </programlisting>
+ We can check now that as expected, the type of <literal>x</literal>
+ has been reconstructed, and with it the
+ type of <literal>f</literal> has been too:
+ <programlisting>
+*Main> :t x
+x :: Integer
+*Main> :t f
+f :: Integer -> b
+ </programlisting>
+ From here, we can apply f to any argument of type Integer and observe the
+ results.
+ <programlisting><![CDATA[
+*Main> let b = f 10
+*Main> :t b
+b :: b
+*Main> b
+<interactive>:1:0:
+ Ambiguous type variable `b' in the constraint:
+ `Show b' arising from a use of `print' at <interactive>:1:0
+*Main> :p b
+b = (_t2::a)
+*Main> seq b ()
+()
+*Main> :t b
+b :: a
+*Main> :p b
+b = Just 10
+*Main> :t b
+b :: Maybe Integer
+*Main> :t f
+f :: Integer -> Maybe Integer
+*Main> f 20
+Just 20
+*Main> map f [1..5]
+[Just 1, Just 2, Just 3, Just 4, Just 5]
+ ]]></programlisting>
+ In the first application of <literal>f</literal>, we had to do
+ some more type reconstruction
+ in order to recover the result type of <literal>f</literal>.
+ But after that, we are free to use
+ <literal>f</literal> normally.
</sect2>
<sect2><title>Tips</title>
<variablelist>
@@ -1865,8 +1933,8 @@ x :: Int
<listitem><para><programlisting>
type MyLongType a = [Maybe [Maybe a]]
-main:Main> :m +GHC.Exts
-main:Main> main
+*Main> :m +GHC.Exts
+*Main> main
Local bindings in scope:
x :: a
Main.hs:15> let x' = unsafeCoerce x :: MyLongType Bool
@@ -1885,7 +1953,25 @@ Main.hs:15> x'
</para></listitem>
</varlistentry>
</variablelist>
- </sect2></sect1>
+ </sect2>
+ <sect2><title>Limitations</title>
+ <para>
+ <itemizedlist>
+ <listitem><para>
+ Implicit parameters (see <xref linkend="implicit-parameters"/>) are only available
+ at the scope of a breakpoint if there is a explicit type signature.
+ </para></listitem>
+ </itemizedlist>
+ <itemizedlist>
+ <listitem><para>
+ Modules compiled by GHCi under the <literal>-fdebugging
+ </literal> flag will perform slower: the debugging mode introduces some overhead.
+ Modules compiled to object code by ghc are not affected.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ </sect1>
<sect1 id="ghci-dot-files">
<title>The <filename>.ghci</filename> file</title>
<indexterm><primary><filename>.ghci</filename></primary><secondary>file</secondary>