"Hello, and welcome to the **IHaskell Notebook**. IHaskell Notebook is similar to an interactive shell along the lines of GHCi. However, it is much more powerful, and provides features such as syntax highlighting, autocompletion, multi-line input cells, integrated documentation, rich output visualization, and more. In this notebook, I'd like to demonstrate many of the awesome features IHaskell provides.\n",
"\n",
"IHaskell is implemented as a language kernel for the [IPython](http://ipython.org) project, which means that although the entire thing is written only in Haskell, we get a beautiful notebook interface practically for free.\n",
"\n",
"We can start with very simple Haskell expressions:"
"-- First of all, we can evaluate simple expressions.\n",
"3 + 5\n",
"\"Hello, \" ++ \"World!\""
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"As you can see, each input cell get an execution number. The first input cell is labeled `In [1]`. Just like in GHCi, the output of the last executed statement or expression is available via the `it` variable - however, in addition, the output of the $n$th cell is available via the `itN` variable. For example, if we wanted to see what the first cell printed, we can go ahead and output that:"
"In addition to simple code cells such as the ones you see, you can also have other types of cells. All of this inline text, for instance, is written using Markdown cells, which support the majority of Github markdown syntax. This lets you embed images and formatting and arbitrary HTML interspersed with your Haskell code. In addition, you can export these notebooks into HTML or even as presentations using `reveal.js`. \n",
"\n",
"Alright, back to code. Let's do something slightly fancier:"
"-- Unlike in GHCi, we can have multi-line expressions.\n",
"concat [\n",
" \"Hello\",\n",
" \", \",\n",
" \"World!\"\n",
" ] :: String"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"In addition to multi-line expressions, IHaskell supports most things that you could put in a standard Haskell file. For example, we can have function bindings without the `let` that GHCi requires. (As long as you group type signatures and their corresponding declarations together, you can use pattern matching and put signatures on your top-level declarations!)"
"IHaskell supports most GHC extensions via the `:extension` directive (or any shorthand thereof)."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><span class='err-msg'>‘interactive:IHaskell172.Thing’ has no constructors (EmptyDataDecls permits this)<br/>In the data declaration for ‘interactive:IHaskell172.Thing’</span>"
],
"text/plain": [
"‘interactive:Ghci172.Thing’ has no constructors (EmptyDataDecls permits this)\n",
"In the data declaration for ‘interactive:Ghci172.Thing’"
"Data declarations do pretty much what you expect, and work fine on multiple lines. If a declaration turns out to be not quite what you wanted, you can just go back, edit it, and re-evaluate the code cell."
"Although this doesn't hold everywhere, we've tried to keep IHaskell relatively similar to GHCi in terms of naming. So, just like in GHCi, you can inspect types with `:type` (or shorthands):"
"If you're looking at this notebook after it's been exported to HTML, you won't be able to see this interactive pane that pops up after this is evaluated. However, you can disable the interactive pager, and instead just show the output below the cell:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"-- Only takes effect on later cells, so stick it in its own cell.\n",
":opt no-pager"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<style>/*\n",
"Custom IHaskell CSS.\n",
"*/\n",
"\n",
"/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
" display: block;\n",
" padding-bottom: 1.3em;\n",
" padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
" display: block;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
"}\n",
".hoogle-text {\n",
" display: block;\n",
"}\n",
".hoogle-name {\n",
" color: green;\n",
" font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
" display: block;\n",
" margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
" font-weight: bold;\n",
" font-style: italic;\n",
"}\n",
".hoogle-module {\n",
" font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
" font-weight: bold;\n",
"}\n",
"\n",
"/* Styles used for basic displays */\n",
".get-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" display: block;\n",
" white-space: pre;\n",
"}\n",
"\n",
".show-type {\n",
" color: green;\n",
" font-weight: bold;\n",
" font-family: monospace;\n",
" margin-left: 1em;\n",
"}\n",
"\n",
".mono {\n",
" font-family: monospace;\n",
" display: block;\n",
"}\n",
"\n",
".err-msg {\n",
" color: red;\n",
" font-style: italic;\n",
" font-family: monospace;\n",
" white-space: pre;\n",
" display: block;\n",
"}\n",
"\n",
"#unshowable {\n",
" color: red;\n",
" font-weight: bold;\n",
"}\n",
"\n",
".err-msg.in.collapse {\n",
" padding-top: 0.7em;\n",
"}\n",
"\n",
"/* Code that will get highlighted before it is highlighted */\n",
".highlight-code {\n",
" white-space: pre;\n",
" font-family: monospace;\n",
"}\n",
"\n",
"/* Hlint styles */\n",
".suggestion-warning { \n",
" font-weight: bold;\n",
" color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
" font-weight: bold;\n",
" color: red;\n",
"}\n",
".suggestion-name {\n",
" font-weight: bold;\n",
"}\n",
"</style><div style='background: rgb(247, 247, 247);'><form><textarea id='code'>class (Real a, Enum a) => Integral a where\n",
" quot :: a -> a -> a\n",
" rem :: a -> a -> a\n",
" div :: a -> a -> a\n",
" mod :: a -> a -> a\n",
" quotRem :: a -> a -> (a, a)\n",
" divMod :: a -> a -> (a, a)\n",
" toInteger :: a -> Integer\n",
" \t-- Defined in ‘GHC.Real’\n",
"instance Integral a => Integral (Tagged s a) -- Defined in ‘Data.Tagged’\n",
"instance Integral Integer -- Defined in ‘GHC.Real’\n",
"instance Integral Int -- Defined in ‘GHC.Real’</textarea></form></div><script>CodeMirror.fromTextArea(document.getElementById('code'), {mode: 'haskell', readOnly: 'nocursor'});</script>\n"
"-- Results are printed as we go, even from a single expression.\n",
"import Control.Monad\n",
"import Control.Concurrent\n",
"\n",
"forM_ [1..5] $ \\x -> do\n",
" print x\n",
" threadDelay $ 200 * 1000"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"This is where the similarities with GHCi end, and the particularly shiny features of IHaskell begin.\n",
"\n",
"Although looking at text outputs is often enough, there are many times where we really want a richer output. Suppose we have a custom data type for color:"
"If we were playing around with designing GUI applications, for instance, we might want to actually *see* these colors, instead of just seeing the text \"Red\", \"Green\", and \"Blue\" when we are debugging.\n",
"\n",
"IHaskell lets you define a custom display mechanism for any data type via its `IHaskellDisplay` typeclass. Since you can use IHaskell in console mode as well as notebook mode, you can provide a list of display outputs for any data type, and the frontend will simply choose the best one. Here's how you would implement a very simple display mechanism for this `Color` data type:"
"The `DisplayData` type has several constructors which let you display your data as plain text, HTML, images (SVG, PNG, JPG), or even as LaTeX code.\n",
"\n",
"In order to ship an extension for IHaskell, simply create a package named `ihaskell-thing` with a module named `IHaskell.Display.Thing`. As long as `ihaskell-thing` is installed, IHaskell will detect and use it automatically.\n",
"\n",
"A number of packages already exist, which we can briefly look at. First, in `ihaskell-basic`, we have very simple displays for data types from `Prelude`."
"</style><div class='collapse-group'><span class='btn btn-default' href='#' id='unshowable'>Unshowable:<span class='show-type'>NoShow</span></span><span class='err-msg collapse'>No instance for (Show NoShow) arising from a use of ‘print’<br/>In a stmt of an interactive GHCi command: print it</span></div><script>$('#unshowable').on('click', function(e) {\n",
" e.preventDefault();\n",
" var $this = $(this);\n",
" var $collapse = $this.closest('.collapse-group').find('.err-msg');\n",
"-- We can display Maybes fancily for Show-able types.\n",
"Just ()\n",
"Nothing\n",
"\n",
"-- But it dies if it's not showable.\n",
"data NoShow = X Int\n",
"Just (X 3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"The `ihaskell-aeson` package adds a display for [Aeson](http://hackage.haskell.org/package/aeson) JSON `Value` types. These are automatically syntax highlighted and formatted nicely."
"This syntax highlighting may not show up in the exported HTML, as it is done on the fly with Javascript. The result looks like this in the notebook:\n",
"The `ihaskell-blaze` package lets you play around with HTML straight from within IHaskell using the [Blaze](http://jaspervdj.be/blaze/tutorial.html) library."
"The `ihaskell-diagrams` package allows you to experiment with the [diagrams](http://projects.haskell.org/diagrams/) package. It requires the Cairo backend."
"-- We can draw diagrams, right in the notebook.\n",
":extension NoMonomorphismRestriction\n",
"import Diagrams.Prelude\n",
"\n",
"-- By Brent Yorgey\n",
"-- Draw a Sierpinski triangle!\n",
"sierpinski 1 = eqTriangle 1\n",
"sierpinski n = s\n",
" ===\n",
" (s ||| s) # centerX\n",
" where s = sierpinski (n-1)\n",
"\n",
"-- The `diagram` function is used to display them in the notebook.\n",
"diagram $ sierpinski 4\n",
" # centerXY\n",
" # fc black\n",
" `atop` square 10\n",
" # fc white"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"Just like with Diagrams, `ihaskell-charts` allows you to use the [Chart](https://github.com/timbod7/haskell-chart/wiki) library for plotting from within IHaskell. (You will need to install `cairo` as well, which may be a bit of a hassle.)"
"-- This example is taken from the haskell-chart documentation.\n",
"import Graphics.Rendering.Chart \n",
"import Data.Default.Class\n",
"import Control.Lens\n",
"\n",
"let values = [\n",
" (\"Mexico City\" , 19.2, 0),\n",
" (\"Mumbai\" , 12.9, 10), \n",
" (\"Sydney\" , 4.3, 0),\n",
" (\"London\" , 8.3, 0), \n",
" (\"New York\" , 8.2, 25)]\n",
" \n",
"pitem (s, v, o) = pitem_value .~ v\n",
" $ pitem_label .~ s\n",
" $ pitem_offset .~ o\n",
" $ def \n",
"\n",
"-- Convert to a renderable in order to display it.\n",
"toRenderable \n",
" $ pie_title .~ \"Relative Population\"\n",
" $ pie_plot . pie_data .~ map pitem values\n",
" $ def"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"By default, both `ihaskell-diagrams` and `ihaskell-chart` use SVG displays. However, the notebook does not support interactive resizing for SVG image. However, if you use `:set no-svg`, all SVG outputs will instead be shown as PNG images, and they can be resized easily."
"Finally, the `ihaskell-magic` chart uses the [magic](http://hackage.haskell.org/package/magic) library (bindings to `libmagic`) to create a display mechanism for `ByteString`s. If you try to load an image, for instance, you will see that image immediately in the notebook."
"-- You could similarly use `:opt lint` to turn it back on.\n",
"f $ 3"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"In addition to `hlint` integration, IHaskell also integrates **Hoogle** for documentation searches. IHaskell provides two directives for searching Hoogle. The first of these, `:document` (or shorthands), looks for exact matches."
"The other provided command is `:hoogle`. This does a normal Hoogle search, and thus lets you use imperfect matching and searching by type signature. This will show you documentation for things that match the desired type signature, as demonstrated below. It automatically formats inline Haskell code and hyperlinks the identifiers to their respective Haddock documentations."
"</style><span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:zip'>zip</a> ∷ [a] → [b] → [(a, b)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>base</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Prelude</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>zip takes two lists and returns a list of corresponding pairs. If one input list is short, excess elements of the longer list are discarded. \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/bytestring/latest/doc/html/Data-ByteString-Builder-Prim.html#v:-62--42--60-'>(>*<)</a> ∷ Monoidal f ⇒ f a → f b → f (a, b)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>bytestring</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.ByteString.Builder.Prim</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>A pairing/concatenation operator for builder primitives, both bounded and fixed size.\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Writer-Class.html#v:listens'>listens</a> ∷ MonadWriter w m ⇒ (w → b) → m a → m (a, b)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>mtl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Control.Monad.Writer.Class</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>listens f m is an action that executes the action m and adds the result of applying f to the output to the value of the computation.\n",
"</div>\n",
"<div class='hoogle-text'></div>\n",
"<div class='hoogle-text'>* f m = liftM (id *** f) (listen\n",
"</div>\n",
"<div class='hoogle-code'>> \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Writer-Class.html#v:listen'>listen</a> ∷ MonadWriter w m ⇒ m a → m (a, w)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>mtl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Control.Monad.Writer.Class</span>)</span><div class='hoogle-doc'></div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/fgl/latest/doc/html/Data-Graph-Inductive-Graph.html#v:lpre'>lpre</a> ∷ Graph gr ⇒ gr a b → Node → [(Node, b)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>fgl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Graph.Inductive.Graph</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>Find all Nodes that link to the given Node and the label of each link. \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/fgl/latest/doc/html/Data-Graph-Inductive-Graph.html#v:lsuc'>lsuc</a> ∷ Graph gr ⇒ gr a b → Node → [(Node, b)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>fgl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Graph.Inductive.Graph</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>Find all Nodes that are linked from the given Node and the label of each link. \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/fgl/latest/doc/html/Data-Graph-Inductive-Query-Monad.html#v:apply'>apply</a> ∷ GT m g a → m g → m (a, g)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>fgl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Graph.Inductive.Query.Monad</span>)</span><div class='hoogle-doc'></div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/QuickCheck/latest/doc/html/Test-QuickCheck-Modifiers.html#v:shrinkState'>shrinkState</a> ∷ ShrinkState s a ⇒ a → s → [(a, s)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>QuickCheck</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Test.QuickCheck.Modifiers</span>)</span><div class='hoogle-doc'></div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/transformers/latest/doc/html/Control-Monad-Trans-RWS-Lazy.html#v:execRWS'>execRWS</a> ∷ RWS r w s a → r → s → (s, w)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>transformers</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Control.Monad.Trans.RWS.Lazy</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>Evaluate a computation with the given initial state and environment, returning the final state and output, discarding the final value. \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/fgl/latest/doc/html/Data-Graph-Inductive-Example.html#v:genUNodes'>genUNodes</a> ∷ Int → [UNode]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>fgl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Graph.Inductive.Example</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>generate list of unlabeled nodes \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/fgl/latest/doc/html/Data-Graph-Inductive-Example.html#v:genLNodes'>genLNodes</a> ∷ Enum a ⇒ a → Int → [LNode a]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>fgl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Graph.Inductive.Example</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>generate list of labeled nodes \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-Map-Lazy.html#v:elemAt'>elemAt</a> ∷ Int → Map k a → (k, a)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>containers</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Map.Lazy</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(log n). Retrieve an element by its index, i.e. by its zero-based index in the sequence sorted by keys. If the index is out of range (less than zero, greater or equal to size of the map), error is called.\n",
"> elemAt 2 (fromList [(5,\"a\"), (3,\"b\")]) Error: index out of range \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/text/latest/doc/html/Data-Text.html#v:breakOnAll'>breakOnAll</a> ∷ Text → Text → [(Text, Text)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>text</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Text</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n+m) Find all non-overlapping instances of needle in haystack. Each element of the returned list consists of a pair:\n",
"</div>\n",
"<div class='hoogle-text'></div>\n",
"<div class='hoogle-text'>* The entire string prior to the kth match (i.e. the prefix)\n",
"</div>\n",
"<div class='hoogle-text'>* The kth match, followed by the remainder of the string\n",
"<div class='hoogle-text'>In (unlikely) bad cases, this function's time complexity degrades towards O(n*m).\n",
"</div>\n",
"<div class='hoogle-text'></div>\n",
"<div class='hoogle-text'>The needle parameter may not be empty. \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/text/latest/doc/html/Data-Text-Lazy.html#v:breakOnAll'>breakOnAll</a> ∷ Text → Text → [(Text, Text)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>text</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Text.Lazy</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>O(n+m) Find all non-overlapping instances of needle in haystack. Each element of the returned list consists of a pair:\n",
"</div>\n",
"<div class='hoogle-text'></div>\n",
"<div class='hoogle-text'>* The entire string prior to the kth match (i.e. the prefix)\n",
"</div>\n",
"<div class='hoogle-text'>* The kth match, followed by the remainder of the string\n",
"<div class='hoogle-text'>This function is strict in its first argument, and lazy in its second.\n",
"</div>\n",
"<div class='hoogle-text'></div>\n",
"<div class='hoogle-text'>In (unlikely) bad cases, this function's time complexity degrades towards O(n*m).\n",
"</div>\n",
"<div class='hoogle-text'></div>\n",
"<div class='hoogle-text'>The needle parameter may not be empty. \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/transformers/latest/doc/html/Control-Monad-Trans-RWS-Lazy.html#v:execRWST'>execRWST</a> ∷ Monad m ⇒ RWST r w s m a → r → s → m (s, w)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>transformers</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Control.Monad.Trans.RWS.Lazy</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>Evaluate a computation with the given initial state and environment, returning the final state and output, discarding the final value. \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/fgl/latest/doc/html/Data-Graph-Inductive-Query-BFS.html#v:level'>level</a> ∷ Graph gr ⇒ Node → gr a b → [(Node, Int)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>fgl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Graph.Inductive.Query.BFS</span>)</span><div class='hoogle-doc'></div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/fgl/latest/doc/html/Data-Graph-Inductive-Query-Dominators.html#v:iDom'>iDom</a> ∷ Graph gr ⇒ gr a b → Node → [(Node, Node)]</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>fgl</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Graph.Inductive.Query.Dominators</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>return immediate dominators for each node of a graph, given a root \n",
"</div>\n",
"</div>\n",
"<span class='hoogle-name'><a target='_blank' href='http://hackage.haskell.org/packages/archive/syb/latest/doc/html/Data-Generics-Twins.html#v:gmapAccumT'>gmapAccumT</a> ∷ Data d ⇒ (∀ e. Data e ⇒ a → e → (a, e)) → a → d → (a, d)</span><span class='hoogle-sub'>(<span class='hoogle-head'>package</span> <span class='hoogle-package'>syb</span>, <span class='hoogle-head'>module</span> <span class='hoogle-module'>Data.Generics.Twins</span>)</span><div class='hoogle-doc'><div class='hoogle-text'>gmapT with accumulation \n",
"All of the code you normally put into IHaskell is (like in GHCi) interpreted. However, sometimes you've perfected a function, and now need it to run faster. In that case, you can go ahead and define a module in a single cell. As long as your module has a module header along the lines of `module Name where`, IHaskell will recognize it as a module. It will create the file `A/B.hs`, compile it, and load it. "
"-- The module is automatically imported unqualified.\n",
"print $ A.B.fib 20\n",
"print $ fib 20"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": false
},
"source": [
"Note that since a new module is imported, all previous bound identifiers are now unbound. For instance, we no longer have access to the `f` function from before:"
"That's it for now! I hope you've enjoyed this little demo of **IHaskell**! There are still a few features that I haven't covered, such as the `show-types` and `show-errors` options, as well as the relatively intelligent autocompletion mechanism and inline type info popups.\n",
"\n",
"I hope you find IHaskell useful, and please report any bugs or features requests [on Github](https://github.com/gibiansky/IHaskell/issues). If you have any comments, want to contribute, or just want to get in touch, don't hesitate to contact me at Andrew dot Gibiansky at Gmail. Contributions are also more than welcome, and I'm happy to help you get started with IHaskell development if you'd like to contribute!\n",
"\n",
"I am also often available at `#ihaskell` on IRC at `chat.freenode.net`, so if I'm around, don't hesitate to ask questions.\n",
"\n",
"Thank you to [Adam Vogt](https://github.com/aavogt), [Stian Håklev](http://reganmian.net/), and [@edechter](https://github.com/edechter) for their testing, bug reporting, pull requests, and general patience!"