16 | title: User browses to localhost:8888/notebooks/example.ipynb
17 | participant js
18 | participant nbs
19 | participant kernel
20 | nbs-->js: ICCP over \nwebsockets
21 | js-->nbs:
22 | nbs-->kernel: ICCP over \nZeroMQ
23 | kernel-->nbs:
24 | nbs->js: sends example.ipynb\n (JSON file)
25 | nbs->kernel: starts up the kernel
26 | note over js: parses JSON structure\ncreates JS representation
27 | note left of js: User types "x=1"\nin a cell\nand executes it
28 | js->nbs: Execute "x=42"
29 | js-js: In[*]
30 | nbs->kernel: Execute "x=42"
31 | kernel-kernel: x=42
32 | kernel->nbs: OK, execution count=1
33 | nbs->js: OK, execution count=1
34 | js-js: In[1]
35 |
36 |
37 | note over kernel: x=42
38 |
44 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/logos/haskell.svg:
--------------------------------------------------------------------------------
1 |
2 |
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, Project Jupyter Contributors
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Talk on IPython frontends and backends for [PyData SV 2014](http://pydata.org/sv2014/)
2 |
3 | Paul Ivanov was responsible for the [Protocol and Frontend portion of the
4 | talk](http://nbviewer.ipython.org/github/ipython/front-to-back/blob/master/Frontends.ipynb).
5 |
6 | Thomas Kluyver was responsible for the Kernels and Kernel Spec portion of the
7 | talk. See the
8 | [IJulia](http://nbviewer.ipython.org/github/ipython/front-to-back/blob/master/IJulia%20Preview.ipynb),
9 | the
10 | [IHaskell](http://nbviewer.ipython.org/github/ipython/front-to-back/blob/master/IHaskell.ipynb),
11 | and the [R
12 | language](http://nbviewer.ipython.org/github/ipython/front-to-back/blob/master/R_demo.ipynb) notebooks.
13 |
14 |
15 | # The IPython protocol, frontends and kernels
16 |
17 | May 03 - 2:20 p.m.
18 |
19 | Paul Ivanov, Thomas Kluyver
20 |
21 | A key idea behind the IPython Notebook is decoupling code execution from user
22 | interfaces. IPython relies on a documented JSON protocol, which can be
23 | implemented by different frontends and different kernels. By implementing the
24 | messaging protocol, new frontends gain the ability to communicate with a kernel
25 | regardless of the kernel implementation language. Conversely, new kernels
26 | automatically gain access to the existing client ecosystem. The IPython project
27 | maintains three different frontends, and there are multiple third party
28 | frontends and kernels already in use. We'll describe some important features of
29 | the messaging protocol, before demonstrating some of our alternative frontends,
30 | including vim-ipython and bipython. We'll show kernels that people have written
31 | in other languages, such as Julia and R, and preview the upcoming features that
32 | will expose these alternative kernels in the Notebook user interface. This talk
33 | is proposed jointly by Paul Ivanov and Thomas Kluyver, both core IPython
34 | developers.
35 |
36 |
--------------------------------------------------------------------------------
/logos/erlang-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
33 |
--------------------------------------------------------------------------------
/logos/julia.svg:
--------------------------------------------------------------------------------
1 |
58 |
--------------------------------------------------------------------------------
/R_demo.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "kernelspec": {
4 | "codemirror_mode": "R",
5 | "display_name": "R",
6 | "language": "R",
7 | "name": "ir"
8 | },
9 | "name": "",
10 | "signature": "sha256:769b53de9bc90dc3041db26edc113bb1a72abdd9c76947f292e60f3eefa53f70"
11 | },
12 | "nbformat": 3,
13 | "nbformat_minor": 0,
14 | "worksheets": [
15 | {
16 | "cells": [
17 | {
18 | "cell_type": "heading",
19 | "level": 2,
20 | "metadata": {},
21 | "source": [
22 | "Basic operations"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "collapsed": false,
28 | "input": [
29 | "print(\"Hello world! Love, R in IPython.\")"
30 | ],
31 | "language": "python",
32 | "metadata": {},
33 | "outputs": []
34 | },
35 | {
36 | "cell_type": "code",
37 | "collapsed": false,
38 | "input": [
39 | "a = 1:78\n",
40 | "a ^ 2"
41 | ],
42 | "language": "python",
43 | "metadata": {},
44 | "outputs": []
45 | },
46 | {
47 | "cell_type": "markdown",
48 | "metadata": {},
49 | "source": [
50 | "Plotting works too:"
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "collapsed": false,
56 | "input": [
57 | "x = seq(0, 2*pi, length.out=50)\n",
58 | "plot(x, sin(x))"
59 | ],
60 | "language": "python",
61 | "metadata": {},
62 | "outputs": []
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {},
67 | "source": [
68 | "No tab completion yet - come and implement it!"
69 | ]
70 | },
71 | {
72 | "cell_type": "heading",
73 | "level": 2,
74 | "metadata": {},
75 | "source": [
76 | "Rich display"
77 | ]
78 | },
79 | {
80 | "cell_type": "markdown",
81 | "metadata": {},
82 | "source": [
83 | "There is a separate `IRdisplay` package with the display API - it will be possible to use the same function calls with `%%R` magics from the IPython kernel.\n",
84 | "\n",
85 | "The plotting example above uses `display_png`."
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "collapsed": false,
91 | "input": [
92 | "library(IRdisplay)\n",
93 | "\n",
94 | "display_html('Repo:takluyver/IRkernel')"
95 | ],
96 | "language": "python",
97 | "metadata": {},
98 | "outputs": []
99 | },
100 | {
101 | "cell_type": "markdown",
102 | "metadata": {},
103 | "source": [
104 | "This is already seeing serious use. Here's a notebook by [Ramnath Vaidyanathan](https://github.com/ramnathv/):"
105 | ]
106 | },
107 | {
108 | "cell_type": "markdown",
109 | "metadata": {},
110 | "source": [
111 | "## Leaflet Routing Machine Plugin\n",
112 | "\n",
113 | "I saw the [following issue](https://github.com/ramnathv/rMaps/issues/45) posted to the [rMaps](http://github.com/ramnathv/rMaps) github repo today.\n",
114 | "\n",
115 | "> I am new to using rMaps and leaflet. I would like to plot the route between two locations. The leaflet routing machine plugin allows us to do this (https://github.com/perliedman/leaflet-routing-machine). I am not quite sure how to use the functions `addAssets()` and `setTemplate()` to be able to use this plugin.\n",
116 | "\n",
117 | "This was a good exercise for me to test whether these newly introduced mechanisms `addAssets` and `setTemplate` would allow one to easily extend the base leaflet binding in [rMaps](http://rmaps.github.io).\n",
118 | "\n",
119 | "Let us start by creating the base map."
120 | ]
121 | },
122 | {
123 | "cell_type": "code",
124 | "collapsed": false,
125 | "input": [
126 | "library(rMaps)\n",
127 | "map = Leaflet$new()\n",
128 | "map$setView(c(40.73846, -73.99413), 16)\n",
129 | "map$tileLayer(provider = 'Stamen.TonerLite')"
130 | ],
131 | "language": "python",
132 | "metadata": {},
133 | "outputs": []
134 | },
135 | {
136 | "cell_type": "code",
137 | "collapsed": false,
138 | "input": [
139 | "display_chart = function(viz){\n",
140 | " y = paste(capture.output(viz$show('iframesrc', cdn = TRUE)), collapse = \"\\n\")\n",
141 | " IRdisplay::display_html(y)\n",
142 | "}"
143 | ],
144 | "language": "python",
145 | "metadata": {},
146 | "outputs": []
147 | },
148 | {
149 | "cell_type": "code",
150 | "collapsed": false,
151 | "input": [
152 | "display_chart(map)"
153 | ],
154 | "language": "python",
155 | "metadata": {},
156 | "outputs": []
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {},
161 | "source": [
162 | "We now want to add a route between the following waypoints. I have chosen the data structure to be an unnamed list of vectors, since it converts easily to the JSON structure expected by by routing plugin."
163 | ]
164 | },
165 | {
166 | "cell_type": "code",
167 | "collapsed": false,
168 | "input": [
169 | "mywaypoints = list(c(40.74119, -73.9925), c(40.73573, -73.99302))"
170 | ],
171 | "language": "python",
172 | "metadata": {},
173 | "outputs": []
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "metadata": {},
178 | "source": [
179 | "In order to use the routing plugin, we first need to add the required js/css assets. I introduced the `addAssets` method in the `dev` version of `rCharts` precisely to serve this need (NOTE: It is currently a little buggy in terms of order in which the assets are specified, but I will take care of that this week)."
180 | ]
181 | },
182 | {
183 | "cell_type": "code",
184 | "collapsed": false,
185 | "input": [
186 | "map$addAssets(\n",
187 | " css = \"http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.css\",\n",
188 | " jshead = \"http://www.liedman.net/leaflet-routing-machine/dist/leaflet-routing-machine.min.js\"\n",
189 | ")\n",
190 | "\n",
191 | "routingTemplate = \"\n",
192 | " \"\n",
201 | "\n",
202 | "map$setTemplate(\n",
203 | " afterScript = sprintf(routingTemplate, RJSONIO::toJSON(mywaypoints))\n",
204 | ")\n",
205 | "display_chart(map)"
206 | ],
207 | "language": "python",
208 | "metadata": {},
209 | "outputs": []
210 | },
211 | {
212 | "cell_type": "markdown",
213 | "metadata": {},
214 | "source": [
215 | "[Original notebook on nbviewer](http://nbviewer.ipython.org/urls/gist.githubusercontent.com/ramnathv/9998388/raw/349d6c6756679610cbb78812911f6b15da56e12f/rmaps_leaflet_routing.ipynb?create=1)"
216 | ]
217 | }
218 | ],
219 | "metadata": {}
220 | }
221 | ]
222 | }
--------------------------------------------------------------------------------
/logos/ocaml.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
100 |
--------------------------------------------------------------------------------
/IJulia Preview.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "kernelspec": {
4 | "codemirror_mode": "julia",
5 | "display_name": "IJulia",
6 | "language": "julia",
7 | "name": "julia"
8 | },
9 | "language": "Julia",
10 | "name": "",
11 | "signature": "sha256:309e1b3ef2f60d19e040236f4a169ce79ae4add9f10ecad7c3788681b4f7c93f"
12 | },
13 | "nbformat": 3,
14 | "nbformat_minor": 0,
15 | "worksheets": [
16 | {
17 | "cells": [
18 | {
19 | "cell_type": "heading",
20 | "level": 1,
21 | "metadata": {},
22 | "source": [
23 | "An IJulia Preview"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {},
29 | "source": [
30 | "This notebook is a preview demo of **IJulia**: a [Julia-language](http://julialang.org/) backend combined with the [IPython](http://ipython.org/) interactive environment. This combination allows you to interact with the Julia language using IPython's powerful [graphical notebook](http://ipython.org/notebook.html), which combines code, formatted text, math, and multimedia in a single document."
31 | ]
32 | },
33 | {
34 | "cell_type": "heading",
35 | "level": 2,
36 | "metadata": {},
37 | "source": [
38 | "Basic Julia interaction"
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {},
44 | "source": [
45 | "Basic mathematical expressions work like you expect:"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "collapsed": false,
51 | "input": [
52 | "1 + sin(3)"
53 | ],
54 | "language": "python",
55 | "metadata": {},
56 | "outputs": []
57 | },
58 | {
59 | "cell_type": "markdown",
60 | "metadata": {},
61 | "source": [
62 | "You can define variables, write loops, and execute arbitrary multiline code blocks. Here is an example of an alternating harmonic series $\\sum_{n=1}^\\infty \\frac{(-1)^n}{n}$ from a [Julia tutorial by Homer Reid](http://homerreid.ath.cx/teaching/18.330/JuliaProgramming.shtml#SimplePrograms):"
63 | ]
64 | },
65 | {
66 | "cell_type": "code",
67 | "collapsed": false,
68 | "input": [
69 | "s = 0.0\n",
70 | "for n = 1:2:10000\n",
71 | " s += 1/n - 1/(n+1)\n",
72 | "end\n",
73 | "s # an expression on the last line (if it doesn't end with \";\") is printed as \"Out\""
74 | ],
75 | "language": "python",
76 | "metadata": {},
77 | "outputs": []
78 | },
79 | {
80 | "cell_type": "markdown",
81 | "metadata": {},
82 | "source": [
83 | "Previous outputs can be referred to via `Out[`*n*`]`, following the IPython, for example `Out[2]` for the result above. You can also use the shorthand `_2`, or `_` for the previous result, as in IPython. Like in Matlab, `ans` can also be used to refer to the previous result, *even if it was not printed* (when the command ended with `;`).\n",
84 | "\n",
85 | "For example, the harmonic series above should be converging (slowly) to $\\ln 2$, and we can check this:"
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "collapsed": false,
91 | "input": [
92 | "Out[2] - log(2)"
93 | ],
94 | "language": "python",
95 | "metadata": {},
96 | "outputs": []
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "Like Matlab or Scipy + Numpy, Julia has lots of mathematical functions and linear algebra built in. For example, we can define a $500\\times500$ random matrix $R$ and form the positive-definite matrix $R^* R$:"
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "collapsed": false,
108 | "input": [
109 | "R = rand(500,500)\n",
110 | "R' * R"
111 | ],
112 | "language": "python",
113 | "metadata": {},
114 | "outputs": []
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {},
119 | "source": [
120 | "(Notice that, by default, only a portion of a large matrix is shown. You didn't really want to read $500^2 = 250,000$ numbers, did you?)"
121 | ]
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "metadata": {},
126 | "source": [
127 | "Tab completion and introspection work"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "collapsed": false,
133 | "input": [
134 | "ran"
135 | ],
136 | "language": "python",
137 | "metadata": {},
138 | "outputs": []
139 | },
140 | {
141 | "cell_type": "heading",
142 | "level": 2,
143 | "metadata": {},
144 | "source": [
145 | "Julia\u2013Python interoperability: SciPy and Matplotlib"
146 | ]
147 | },
148 | {
149 | "cell_type": "markdown",
150 | "metadata": {},
151 | "source": [
152 | "Julia can easily and transparently call external Python code using a package called [PyCall](https://github.com/stevengj/PyCall.jl), and to illustrate that capability we will show some examples calling [SciPy](http://www.scipy.org/) and [Matplotlib](http://matplotlib.org/) from Julia.\n",
153 | "\n",
154 | "For example, we can use the [Newton solver in scipy.optimize](http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html) to solve a transcendental equation $\\cos(x) - x = 0$ given a *Julia* function:"
155 | ]
156 | },
157 | {
158 | "cell_type": "code",
159 | "collapsed": false,
160 | "input": [
161 | "using PyCall\n",
162 | "@pyimport scipy.optimize as so\n",
163 | "so.newton(x -> cos(x) - x, 1)"
164 | ],
165 | "language": "python",
166 | "metadata": {},
167 | "outputs": []
168 | },
169 | {
170 | "cell_type": "markdown",
171 | "metadata": {},
172 | "source": [
173 | "We can use the same `@pyimport` syntax to import Matplotlib (specifically, the `matplotlib.pyplot` module), but to integrate Matplotlib's graphics with the IJulia display requires a little more work. To simplify this, we've created a [PyPlot module](https://github.com/stevengj/PyPlot.jl) for Julia:"
174 | ]
175 | },
176 | {
177 | "cell_type": "code",
178 | "collapsed": false,
179 | "input": [
180 | "using PyPlot\n",
181 | "x = linspace(0,2*pi,1000)\n",
182 | "y = sin(3*x + 4*cos(2*x))\n",
183 | "plot(x, y, color=\"red\", linewidth=2.0, linestyle=\"--\")\n",
184 | "ylabel(\"the y axis\")\n",
185 | "xlabel(\"the x axis\")\n",
186 | "title(\"a sinusoidally-modulated sinusoid\")"
187 | ],
188 | "language": "python",
189 | "metadata": {},
190 | "outputs": []
191 | },
192 | {
193 | "cell_type": "markdown",
194 | "metadata": {},
195 | "source": [
196 | "Notice that, by default, the plots are displayed inline (just as for the `%pylab inline` \"magic\" in IPython). This kind of multimedia display can be enabled for *any* Julia object, as explained in the next section."
197 | ]
198 | },
199 | {
200 | "cell_type": "heading",
201 | "level": 2,
202 | "metadata": {},
203 | "source": [
204 | "Multimedia display in IJulia"
205 | ]
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {},
210 | "source": [
211 | "To start with, the simplest thing is to provide the MIME type of the data when you call `display`, which allows you to pass \"raw\" data in the corresponding format:"
212 | ]
213 | },
214 | {
215 | "cell_type": "code",
216 | "collapsed": false,
217 | "input": [
218 | "display(\"text/html\", \"\"\"Hello world in HTML!\"\"\")"
219 | ],
220 | "language": "python",
221 | "metadata": {},
222 | "outputs": []
223 | },
224 | {
225 | "cell_type": "markdown",
226 | "metadata": {},
227 | "source": [
228 | "However, it will be more common to attach this information to types, so that they display correctly automatically. For example, let's define a simple `HTML` type in Julia that contains a string and automatically displays as HTML (given an HTML-capable backend such as IJulia):"
229 | ]
230 | },
231 | {
232 | "cell_type": "code",
233 | "collapsed": false,
234 | "input": [
235 | "type HTML\n",
236 | " s::String\n",
237 | "end\n",
238 | "import Base.writemime\n",
239 | "writemime(io::IO, ::MIME\"text/html\", x::HTML) = print(io, x.s)"
240 | ],
241 | "language": "python",
242 | "metadata": {},
243 | "outputs": []
244 | },
245 | {
246 | "cell_type": "markdown",
247 | "metadata": {},
248 | "source": [
249 | "Here, `writemime` is just a function that writes `x` in the corresponding format (`text/html`) to the I/O stream `io`. The `MIME` is a bit of magic to allow Julia's [multiple dispatch](http://en.wikipedia.org/wiki/Multiple_dispatch) to automatically select the correct `writemime` function for a given MIME type (here `\"text/html\"`) and object type (here `HTML`). We also needed an `import` statement in order to add new methods to an existing function from another module.\n",
250 | "\n",
251 | "This `writemime` definition is all that we need to make any object of type `HTML` display automatically as HTML text in IJulia:"
252 | ]
253 | },
254 | {
255 | "cell_type": "code",
256 | "collapsed": false,
257 | "input": [
258 | "x = HTML(\"
Hello from a bulleted list!
\")"
259 | ],
260 | "language": "python",
261 | "metadata": {},
262 | "outputs": []
263 | },
264 | {
265 | "cell_type": "code",
266 | "collapsed": false,
267 | "input": [
268 | "display(x)\n",
269 | "println(x)"
270 | ],
271 | "language": "python",
272 | "metadata": {},
273 | "outputs": []
274 | }
275 | ],
276 | "metadata": {}
277 | }
278 | ]
279 | }
--------------------------------------------------------------------------------
/underscore-min.js:
--------------------------------------------------------------------------------
1 | // Underscore.js 1.6.0
2 | // http://underscorejs.org
3 | // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
4 | // Underscore may be freely distributed under the MIT license.
5 | (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?void(this._wrapped=n):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.6.0";var A=j.each=j.forEach=function(n,t,e){if(null==n)return n;if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return;return n};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var O="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},j.find=j.detect=function(n,t,r){var e;return k(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var k=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:k(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,j.property(t))},j.where=function(n,t){return j.filter(n,j.matches(t))},j.findWhere=function(n,t){return j.find(n,j.matches(t))},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);var e=-1/0,u=-1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;o>u&&(e=n,u=o)}),e},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);var e=1/0,u=1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;u>o&&(e=n,u=o)}),e},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return null==t||r?(n.length!==+n.length&&(n=j.values(n)),n[j.random(n.length-1)]):j.shuffle(n).slice(0,Math.max(0,t))};var E=function(n){return null==n?j.identity:j.isFunction(n)?n:j.property(n)};j.sortBy=function(n,t,r){return t=E(t),j.pluck(j.map(n,function(n,e,u){return{value:n,index:e,criteria:t.call(r,n,e,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=E(r),A(t,function(i,a){var o=r.call(e,i,a,t);n(u,o,i)}),u}};j.groupBy=F(function(n,t,r){j.has(n,t)?n[t].push(r):n[t]=[r]}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=E(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])t?[]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.partition=function(n,t){var r=[],e=[];return A(n,function(n){(t(n)?r:e).push(n)}),[r,e]},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.contains(t,n)})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){for(var r=0,e=t.slice(),u=0,i=e.length;i>u;u++)e[u]===j&&(e[u]=arguments[r++]);for(;r=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u),e=u=null):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o,c=function(){var l=j.now()-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u),i=u=null))};return function(){i=this,u=arguments,a=j.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u),i=u=null),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return j.partial(t,n)},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=function(n){if(!j.isObject(n))return[];if(w)return w(n);var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o)&&"constructor"in n&&"constructor"in t)return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.constant=function(n){return function(){return n}},j.property=function(n){return function(t){return t[n]}},j.matches=function(n){return function(t){if(t===n)return!0;for(var r in n)if(n[r]!==t[r])return!1;return!0}},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},j.now=Date.now||function(){return(new Date).getTime()};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};T.unescape=j.invert(T.escape);var I={escape:new RegExp("["+j.keys(T.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(T.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(I[n],function(t){return T[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),"function"==typeof define&&define.amd&&define("underscore",[],function(){return j})}).call(this);
6 | //# sourceMappingURL=underscore-min.map
--------------------------------------------------------------------------------
/IHaskell.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "language": "haskell",
4 | "name": "",
5 | "signature": "sha256:0866ba3c2a15da31a719190dea10c3c740d34e438328dabcd7614ba286e29a23"
6 | },
7 | "nbformat": 3,
8 | "nbformat_minor": 0,
9 | "worksheets": [
10 | {
11 | "cells": [
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | "\n",
17 | "\n",
18 | "IHaskell Notebook\n",
19 | "===\n",
20 | "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",
21 | "\n",
22 | "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",
23 | "\n",
24 | "We can start with very simple Haskell expressions:"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "collapsed": false,
30 | "input": [
31 | "-- First of all, we can evaluate simple expressions.\n",
32 | "3 + 5\n",
33 | "\"Hello, \" ++ \"World!\""
34 | ],
35 | "language": "python",
36 | "metadata": {},
37 | "outputs": []
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {},
42 | "source": [
43 | "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:"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "collapsed": false,
49 | "input": [
50 | "it1"
51 | ],
52 | "language": "python",
53 | "metadata": {},
54 | "outputs": []
55 | },
56 | {
57 | "cell_type": "code",
58 | "collapsed": false,
59 | "input": [
60 | "-- Unlike in GHCi, we can have multi-line expressions.\n",
61 | "concat [\n",
62 | " \"Hello\",\n",
63 | " \", \",\n",
64 | " \"World!\"\n",
65 | " ] :: String"
66 | ],
67 | "language": "python",
68 | "metadata": {},
69 | "outputs": []
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {},
74 | "source": [
75 | "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!)"
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "collapsed": false,
81 | "input": [
82 | "thing :: String -> Int -> Int\n",
83 | "thing \"no\" _ = 100\n",
84 | "thing str int = int + length str\n",
85 | "\n",
86 | "thing \"no\" 10\n",
87 | "thing \"ah\" 10"
88 | ],
89 | "language": "python",
90 | "metadata": {},
91 | "outputs": []
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {},
96 | "source": [
97 | "So far we've just looked at pure functions, but nothing is stopping us from doing IO."
98 | ]
99 | },
100 | {
101 | "cell_type": "code",
102 | "collapsed": false,
103 | "input": [
104 | "print \"What's going on?\""
105 | ],
106 | "language": "python",
107 | "metadata": {},
108 | "outputs": []
109 | },
110 | {
111 | "cell_type": "markdown",
112 | "metadata": {},
113 | "source": [
114 | "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):"
115 | ]
116 | },
117 | {
118 | "cell_type": "code",
119 | "collapsed": false,
120 | "input": [
121 | "-- We can look at types like in GHCi.\n",
122 | ":ty 3 + 3"
123 | ],
124 | "language": "python",
125 | "metadata": {},
126 | "outputs": []
127 | },
128 | {
129 | "cell_type": "markdown",
130 | "metadata": {},
131 | "source": [
132 | "The same goes for the `:info` command. However, unlike GHCi, which simply prints info, the IHaskell notebook brings up a separate pane."
133 | ]
134 | },
135 | {
136 | "cell_type": "code",
137 | "collapsed": false,
138 | "input": [
139 | "-- What is the Integral typeclass?\n",
140 | ":info Integral"
141 | ],
142 | "language": "python",
143 | "metadata": {},
144 | "outputs": []
145 | },
146 | {
147 | "cell_type": "markdown",
148 | "metadata": {},
149 | "source": [
150 | "We can now write slightly more complicated scripts."
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "collapsed": false,
156 | "input": [
157 | "-- Results are printed as we go, even from a single expression.\n",
158 | "import Control.Monad\n",
159 | "import Control.Concurrent\n",
160 | "\n",
161 | "forM_ [1..5] $ \\x -> do\n",
162 | " print x\n",
163 | " threadDelay $ 200 * 1000"
164 | ],
165 | "language": "python",
166 | "metadata": {},
167 | "outputs": []
168 | },
169 | {
170 | "cell_type": "markdown",
171 | "metadata": {},
172 | "source": [
173 | "This is where the similarities with GHCi end, and the particularly shiny features of IHaskell begin.\n",
174 | "\n",
175 | "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:"
176 | ]
177 | },
178 | {
179 | "cell_type": "code",
180 | "collapsed": false,
181 | "input": [
182 | "data Color = Red | Green | Blue"
183 | ],
184 | "language": "python",
185 | "metadata": {},
186 | "outputs": []
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {},
191 | "source": [
192 | "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",
193 | "\n",
194 | "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:"
195 | ]
196 | },
197 | {
198 | "cell_type": "code",
199 | "collapsed": false,
200 | "input": [
201 | "import IHaskell.Display\n",
202 | "\n",
203 | "instance IHaskellDisplay Color where\n",
204 | " display color = return $ Display [html code]\n",
205 | " where\n",
206 | " code = concat [\"
Look!
\"]\n",
209 | " css Red = \"red\"\n",
210 | " css Blue = \"blue\"\n",
211 | " css Green = \"green\""
212 | ],
213 | "language": "python",
214 | "metadata": {},
215 | "outputs": []
216 | },
217 | {
218 | "cell_type": "markdown",
219 | "metadata": {},
220 | "source": [
221 | "Once we define a custom `display :: a -> IO Display` function, we can simply output a `Color`:"
222 | ]
223 | },
224 | {
225 | "cell_type": "code",
226 | "collapsed": false,
227 | "input": [
228 | "Red\n",
229 | "Green\n",
230 | "Blue"
231 | ],
232 | "language": "python",
233 | "metadata": {},
234 | "outputs": []
235 | },
236 | {
237 | "cell_type": "markdown",
238 | "metadata": {},
239 | "source": [
240 | "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",
241 | "\n",
242 | "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",
243 | "\n",
244 | "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`."
245 | ]
246 | },
247 | {
248 | "cell_type": "code",
249 | "collapsed": false,
250 | "input": [
251 | "-- We can display Maybes fancily for Show-able types.\n",
252 | "Just ()\n",
253 | "Nothing\n",
254 | "\n",
255 | "-- But it dies if it's not showable.\n",
256 | "data NoShow = X Int\n",
257 | "Just (X 3)"
258 | ],
259 | "language": "python",
260 | "metadata": {},
261 | "outputs": []
262 | },
263 | {
264 | "cell_type": "heading",
265 | "level": 2,
266 | "metadata": {},
267 | "source": [
268 | "IHaskell special features"
269 | ]
270 | },
271 | {
272 | "cell_type": "markdown",
273 | "metadata": {},
274 | "source": [
275 | "In addition to displaying outputs in a rich format, IHaskell has a bunch of useful features.\n",
276 | "\n",
277 | "For instance, the popular linting tool `hlint` is integrated and turned on by default. Let's write some ugly code, and see what it tells us:"
278 | ]
279 | },
280 | {
281 | "cell_type": "code",
282 | "collapsed": false,
283 | "input": [
284 | "-- There is also hlint integration enabled by default.\n",
285 | "-- If you write sketchy code, it will tell you:\n",
286 | "f :: Int -> Int\n",
287 | "f x = x + 1\n",
288 | "\n",
289 | "-- Most warnings are orange...\n",
290 | "f $ 3\n",
291 | "\n",
292 | "-- But more severe warnings are red.\n",
293 | "putStrLn (show 3)\n",
294 | "do\n",
295 | " return 3"
296 | ],
297 | "language": "python",
298 | "metadata": {},
299 | "outputs": []
300 | },
301 | {
302 | "cell_type": "markdown",
303 | "metadata": {},
304 | "source": [
305 | "If you're an experienced Haskeller, though, and don't want `hlint` telling you what to do, you can easily turn it off with `:opt no-lint`."
306 | ]
307 | },
308 | {
309 | "cell_type": "markdown",
310 | "metadata": {},
311 | "source": [
312 | "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."
313 | ]
314 | },
315 | {
316 | "cell_type": "code",
317 | "collapsed": false,
318 | "input": [
319 | ":doc filterM"
320 | ],
321 | "language": "python",
322 | "metadata": {},
323 | "outputs": []
324 | },
325 | {
326 | "cell_type": "markdown",
327 | "metadata": {},
328 | "source": [
329 | "The other provided command is `:hoogle`. This does a normal Hoogle search, and thus lets you use imperfect matching and searching by type signature."
330 | ]
331 | },
332 | {
333 | "cell_type": "code",
334 | "collapsed": false,
335 | "input": [
336 | ":hoogle :: [a] -> [(a, b)]"
337 | ],
338 | "language": "python",
339 | "metadata": {},
340 | "outputs": []
341 | },
342 | {
343 | "cell_type": "markdown",
344 | "metadata": {},
345 | "source": [
346 | "If you need a refresher on all of the options, you can just use `:help`:"
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "collapsed": false,
352 | "input": [
353 | ":help"
354 | ],
355 | "language": "python",
356 | "metadata": {},
357 | "outputs": []
358 | },
359 | {
360 | "cell_type": "markdown",
361 | "metadata": {},
362 | "source": [
363 | "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. "
364 | ]
365 | },
366 | {
367 | "cell_type": "code",
368 | "collapsed": false,
369 | "input": [
370 | "-- If your code isn't running fast enough, you can just put it into a module.\n",
371 | "module A.B where\n",
372 | "\n",
373 | "fib 0 = 1\n",
374 | "fib 1 = 1\n",
375 | "fib n = fib (n-1) + fib (n-2)"
376 | ],
377 | "language": "python",
378 | "metadata": {},
379 | "outputs": []
380 | },
381 | {
382 | "cell_type": "markdown",
383 | "metadata": {},
384 | "source": [
385 | "Note that the module is by default imported unqualified, as though you had typed `import A.B`."
386 | ]
387 | },
388 | {
389 | "cell_type": "code",
390 | "collapsed": false,
391 | "input": [
392 | "-- The module is automatically imported unqualified.\n",
393 | "print $ A.B.fib 20\n",
394 | "print $ fib 20"
395 | ],
396 | "language": "python",
397 | "metadata": {},
398 | "outputs": []
399 | }
400 | ],
401 | "metadata": {}
402 | }
403 | ]
404 | }
--------------------------------------------------------------------------------
/logos/python-logo-generic.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
270 |
--------------------------------------------------------------------------------
/Frontends.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "name": "",
4 | "signature": "sha256:51ca2640929c4aea4addb291eac93429243e4831f1ff02eaf6aa4422201740ae"
5 | },
6 | "nbformat": 3,
7 | "nbformat_minor": 0,
8 | "worksheets": [
9 | {
10 | "cells": [
11 | {
12 | "cell_type": "markdown",
13 | "metadata": {},
14 | "source": [
15 | "
\n",
694 | "\n",
695 | "### PSA: vim-ipython common problem (e.g. OS X)\n",
696 | "\n",
697 | "Vim needs to be compiled with Python support (`vim --version | grep +python`)\n",
698 | "AND the Python linked must have IPython with ZeroMQ support\n",
699 | "\n",
700 | "HOWEVER: the Python linked **does not** need to be your preferred Python.\n",
701 | "\n",
702 | "Solution: either install IPython and PyZMQ into system Python, or compile vim\n",
703 | "against a Python which has IPython and PyZMQ (Python that comes with Anaconda,\n",
704 | "for example)"
705 | ]
706 | },
707 | {
708 | "cell_type": "markdown",
709 | "metadata": {},
710 | "source": [
711 | "
"
788 | ]
789 | },
790 | {
791 | "cell_type": "markdown",
792 | "metadata": {},
793 | "source": [
794 | "In any Python code you have lying around, do this:\n",
795 | "\n",
796 | "```python\n",
797 | "import IPython; IPython.embed_kernel()\n",
798 | "```\n",
799 | "\n",
800 | "When that code runs, it will prompt something like this:\n",
801 | "\n",
802 | " NOTE: When using the `ipython kernel` entry point, Ctrl-C will not work.\n",
803 | "\n",
804 | " To exit, you will have to explicitly quit this process, by either sending\n",
805 | " \"quit\" from a client, or using Ctrl-\\ in UNIX-like environments.\n",
806 | "\n",
807 | " To read more about this, see https://github.com/ipython/ipython/issues/2049\n",
808 | "\n",
809 | "\n",
810 | " To connect another client to this kernel, use:\n",
811 | " --existing kernel-5979.json\n",
812 | "\n",
813 | "(demo if time permits)"
814 | ]
815 | },
816 | {
817 | "cell_type": "markdown",
818 | "metadata": {},
819 | "source": [
820 | "