Skip to content

Instantly share code, notes, and snippets.

@DougBurke
Created June 22, 2021 14:25
Show Gist options
  • Save DougBurke/11009ad97320e352c21a0d7558bb0b8b to your computer and use it in GitHub Desktop.
Save DougBurke/11009ad97320e352c21a0d7558bb0b8b to your computer and use it in GitHub Desktop.
IHaskell and the custom mimetype - see https://github.com/gibiansky/IHaskell/issues/1173
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ghc-8.10.4"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"ihaskell-0.10.2.0"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"hvega-0.11.0.1"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"ihaskell-hvega-0.3.2.0"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":!ghc-pkg latest ghc\n",
":!ghc-pkg latest ihaskell\n",
":!ghc-pkg latest hvega\n",
":!ghc-pkg latest ihaskell-hvega"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
":ext OverloadedStrings"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import qualified Graphics.Vega.VegaLite as VL\n",
"import Graphics.Vega.VegaLite hiding (filter, repeat)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a relatively simple vega-lite visualization and should look something\n",
"like \n",
"\n",
"![image](https://raw.githubusercontent.com/DougBurke/hvega/master/hvega/images/example-car.png)\n",
"\n",
"but without the gray background."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"simple =\n",
" let cars = dataFromUrl \"https://vega.github.io/vega-datasets/data/cars.json\" []\n",
"\n",
" enc = encoding\n",
" . position X [ PName \"Horsepower\", PmType Quantitative ]\n",
" . position Y [ PName \"Miles_per_Gallon\", PmType Quantitative, PTitle \"Miles per Gallon\" ]\n",
" . color [ MName \"Origin\" ]\n",
"\n",
" in toVegaLite [ cars, mark Circle [MTooltip TTEncoding], enc [] ]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>/* 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",
".get-type {\n",
"color: green;\n",
"font-weight: bold;\n",
"font-family: monospace;\n",
"display: block;\n",
"white-space: pre-wrap;\n",
"}\n",
".show-type {\n",
"color: green;\n",
"font-weight: bold;\n",
"font-family: monospace;\n",
"margin-left: 1em;\n",
"}\n",
".mono {\n",
"font-family: monospace;\n",
"display: block;\n",
"}\n",
".err-msg {\n",
"color: red;\n",
"font-style: italic;\n",
"font-family: monospace;\n",
"white-space: pre;\n",
"display: block;\n",
"}\n",
"#unshowable {\n",
"color: red;\n",
"font-weight: bold;\n",
"}\n",
".err-msg.in.collapse {\n",
"padding-top: 0.7em;\n",
"}\n",
".highlight-code {\n",
"white-space: pre;\n",
"font-family: monospace;\n",
"}\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='get-type'>simple :: VegaLite</span>"
],
"text/plain": [
"simple :: VegaLite"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Check the type\n",
":t simple"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we have `ihaskell-hvega` available we can view it directly\n",
"in `ihaskell-notebook`, but not `ihaskell-lab` which will throw up\n",
"an error\n",
"\n",
" Javascript Error: requirejs is not defined"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"requirejs.config({baseUrl: 'https://cdn.jsdelivr.net/npm/',paths: {'vega-embed': 'vega-embed@6?noext','vega-lib': 'vega-lib?noext','vega-lite': 'vega-lite@4?noext','vega': 'vega@5?noext'}});var ndiv = document.createElement('div');ndiv.innerHTML = 'Awesome Vega-Lite visualization to appear here';element[0].appendChild(ndiv);require(['vega-embed'],function(vegaEmbed){vegaEmbed(ndiv,{\"mark\":{\"tooltip\":{\"content\":\"encoding\"},\"type\":\"circle\"},\"data\":{\"url\":\"https://vega.github.io/vega-datasets/data/cars.json\"},\"$schema\":\"https://vega.github.io/schema/vega-lite/v4.json\",\"encoding\":{\"color\":{\"field\":\"Origin\"},\"x\":{\"field\":\"Horsepower\",\"type\":\"quantitative\"},\"y\":{\"field\":\"Miles_per_Gallon\",\"title\":\"Miles per Gallon\",\"type\":\"quantitative\"}}}).then(function (result) { console.log(result); }).catch(function (error) { ndiv.innerHTML = 'There was an error: ' + error; });});"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"simple"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If viewed in `ihaskell-lab` then we have to use `vlShow` from `ihaskell-hvega`:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.vegalite.v4+json": {
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "https://vega.github.io/vega-datasets/data/cars.json"
},
"encoding": {
"color": {
"field": "Origin"
},
"x": {
"field": "Horsepower",
"type": "quantitative"
},
"y": {
"field": "Miles_per_Gallon",
"title": "Miles per Gallon",
"type": "quantitative"
}
},
"mark": {
"tooltip": {
"content": "encoding"
},
"type": "circle"
}
},
"image/png": "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"
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"vlShow simple"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see if we can recreate the \"rich display\" feature - this is based heavily on\n",
"[ihaskell-hvega](https://github.com/DougBurke/hvega/tree/main/ihaskell-hvega):"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import qualified Data.Text.Lazy as LT\n",
"\n",
"import Data.Aeson.Text (encodeToLazyText)\n",
"\n",
"import IHaskell.Display (IHaskellDisplay(..), Display(..)\n",
" , javascript, vegalite, custom)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is the approach taken for `ihaskell-notebook` which creates the necessary HTML and Javascript code to display\n",
"the visualization with the Vega-Embed Javascript library:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"newtype Notebook = Notebook VegaLite\n",
"\n",
"instance IHaskellDisplay Notebook where\n",
" display (Notebook vl) =\n",
"\n",
" let -- Note: need to look in the package.json files for these packages\n",
" -- to find the \"full name\" (the contents of the jsdelivr key),\n",
" -- since requirejs does seem to like appending .js to everything.\n",
" --\n",
" jsname n v = \"'https://cdn.jsdelivr.net/npm/\"\n",
" <> n\n",
" <> \"@\" <> v\n",
" <> \"/build/\"\n",
" <> n <> \".min'\"\n",
"\n",
" -- Should the config be set on require or requirejs?\n",
" --\n",
" -- These versions are known to work; later versions\n",
" -- do not work but I have not tried to work out the\n",
" -- latest version that does work.\n",
" --\n",
" config = \"requirejs({paths:{vg:\" <> jsname \"vega\" \"3.2.1\"\n",
" <> \",vl:\" <> jsname \"vega-lite\" \"2.3.0\"\n",
" <> \",vge:\" <> jsname \"vega-embed\" \"3.5.2\"\n",
" <> \"},shim:{vge:{deps:['vg.global','vl.global']}\"\n",
"\n",
" <> \",vl:{deps:['vg']}\"\n",
" <> \"}});\"\n",
" <> \"define('vg.global',['vg'],function(g){window.vega = g;});\"\n",
" <> \"define('vl.global',['vl'],function(g){window.vl = g;});\"\n",
"\n",
" -- rely on the element variable being set up; it appears to be an array\n",
" -- so use the first element to add the div to.\n",
" makeDiv = \"var ndiv = document.createElement('div');\"\n",
" <> \"ndiv.innerHTML = \"\n",
" <> \"'Awesome Vega-Lite visualization to appear here';\"\n",
" <> \"element[0].appendChild(ndiv);\"\n",
"\n",
" js = LT.unpack (encodeToLazyText (fromVL vl))\n",
"\n",
" -- Use the div element we have just created for the plot.\n",
" -- More options could be passed to vegaEmbed.\n",
" --\n",
" plot = \"require(['vge'],function(vegaEmbed){\"\n",
" <> \"vegaEmbed(ndiv,\" <> js <> \").then(\"\n",
" <> \"function (result) { console.log(result); }).catch(\"\n",
" <> \"function (error) { ndiv.innerHTML = \"\n",
" <> \"'There was an error: ' + error; });\"\n",
" <> \"});\"\n",
"\n",
" ds = [javascript (config <> makeDiv <> plot)]\n",
"\n",
" in pure (Display ds)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As I am running this in `ihaskell-lab` I expect it to fail. I have not had the energy or desire to slog through the JS code to understand what is wrong here."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"requirejs({paths:{vg:'https://cdn.jsdelivr.net/npm/vega@3.2.1/build/vega.min',vl:'https://cdn.jsdelivr.net/npm/vega-lite@2.3.0/build/vega-lite.min',vge:'https://cdn.jsdelivr.net/npm/vega-embed@3.5.2/build/vega-embed.min'},shim:{vge:{deps:['vg.global','vl.global']},vl:{deps:['vg']}}});define('vg.global',['vg'],function(g){window.vega = g;});define('vl.global',['vl'],function(g){window.vl = g;});var ndiv = document.createElement('div');ndiv.innerHTML = 'Awesome Vega-Lite visualization to appear here';element[0].appendChild(ndiv);require(['vge'],function(vegaEmbed){vegaEmbed(ndiv,{\"mark\":{\"tooltip\":{\"content\":\"encoding\"},\"type\":\"circle\"},\"data\":{\"url\":\"https://vega.github.io/vega-datasets/data/cars.json\"},\"$schema\":\"https://vega.github.io/schema/vega-lite/v4.json\",\"encoding\":{\"color\":{\"field\":\"Origin\"},\"x\":{\"field\":\"Horsepower\",\"type\":\"quantitative\"},\"y\":{\"field\":\"Miles_per_Gallon\",\"title\":\"Miles per Gallon\",\"type\":\"quantitative\"}}}).then(function (result) { console.log(result); }).catch(function (error) { ndiv.innerHTML = 'There was an error: ' + error; });});"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"Notebook simple"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, Jupyter comes with support for the vegalite mime-type, as does IHaskell, but there\n",
"are multiple versions of the mimetype and IHaskell supports an \"old\" version, so I'd like\n",
"to see if we can use the \"recent\" custom-mimetype support to work. I believe this is only\n",
"supported by the \"lab\" version, not \"notebook\".\n",
"\n",
"First let's explore the existing support for the Vega-Lite mimetype by using the\n",
"`IHaskell.Display.vegalite` routine which wraps up a string and converts a `DisplayData`\n",
"item:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>/* 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",
".get-type {\n",
"color: green;\n",
"font-weight: bold;\n",
"font-family: monospace;\n",
"display: block;\n",
"white-space: pre-wrap;\n",
"}\n",
".show-type {\n",
"color: green;\n",
"font-weight: bold;\n",
"font-family: monospace;\n",
"margin-left: 1em;\n",
"}\n",
".mono {\n",
"font-family: monospace;\n",
"display: block;\n",
"}\n",
".err-msg {\n",
"color: red;\n",
"font-style: italic;\n",
"font-family: monospace;\n",
"white-space: pre;\n",
"display: block;\n",
"}\n",
"#unshowable {\n",
"color: red;\n",
"font-weight: bold;\n",
"}\n",
".err-msg.in.collapse {\n",
"padding-top: 0.7em;\n",
"}\n",
".highlight-code {\n",
"white-space: pre;\n",
"font-family: monospace;\n",
"}\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='get-type'>vegalite :: String -> DisplayData</span>"
],
"text/plain": [
"vegalite :: String -> DisplayData"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t vegalite"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Vega-Lite is a JSON specification so let's try an empty map, which is invalid so it's nice we error out here:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.vegalite.v4+json": {}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"vegalite \"{}\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We have a valid Vega-Lite visualization in `simple`, so let's convert that to a string (`fromVL` converts a Vega-Lite item to an Aeson Value):"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"simpleStr = LT.unpack (encodeToLazyText (fromVL simple))"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{\"mark\":{\"tooltip\":{\"content\":\"encoding\"},\"type\":\"circle\"},\"data\":{\"url\":\"https://vega.github.io/vega-datasets/data/cars.json\"},\"$schema\":\"https://vega.github.io/schema/vega-lite/v4.json\",\"encoding\":{\"color\":{\"field\":\"Origin\"},\"x\":{\"field\":\"Horsepower\",\"type\":\"quantitative\"},\"y\":{\"field\":\"Miles_per_Gallon\",\"title\":\"Miles per Gallon\",\"type\":\"quantitative\"}}}"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"putStrLn simpleStr"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.vegalite.v4+json": {
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "https://vega.github.io/vega-datasets/data/cars.json"
},
"encoding": {
"color": {
"field": "Origin"
},
"x": {
"field": "Horsepower",
"type": "quantitative"
},
"y": {
"field": "Miles_per_Gallon",
"title": "Miles per Gallon",
"type": "quantitative"
}
},
"mark": {
"tooltip": {
"content": "encoding"
},
"type": "circle"
}
},
"image/png": "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"
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"vegalite simpleStr"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So, what I want to be able to do is to use the `custom` mimetype to replicate this.\n",
"\n",
"However, first I should find out what mimetype is actually being used by IHaskell for vega and vegalite, since I looked at this many moons ago:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"import IHaskell.IPython.Types (MimeType(MimeVega, MimeVegalite))"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"application/vnd.vega.v5+json"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"MimeVega"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"application/vnd.vegalite.v4+json"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"MimeVegalite"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Aha - these are a lot newer than I remember. So I may not need this just yet, but let's see if I can replicate the MimeVegalite version (which is presumably what `vegalite simpleStr` is using):"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"newtype Lab = Lab VegaLite\n",
"\n",
"instance IHaskellDisplay Lab where\n",
" display (Lab vl) =\n",
"\n",
" let js = LT.unpack (encodeToLazyText (fromVL vl))\n",
"\n",
" mtype = \"application/vnd.vegalite.v4+json\"\n",
" ds = [custom mtype js]\n",
"\n",
" in pure (Display ds)"
]
},
{
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"The moment of truth:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.vegalite.v4+json": "{\"mark\":{\"tooltip\":{\"content\":\"encoding\"},\"type\":\"circle\"},\"data\":{\"url\":\"https://vega.github.io/vega-datasets/data/cars.json\"},\"$schema\":\"https://vega.github.io/schema/vega-lite/v4.json\",\"encoding\":{\"color\":{\"field\":\"Origin\"},\"x\":{\"field\":\"Horsepower\",\"type\":\"quantitative\"},\"y\":{\"field\":\"Miles_per_Gallon\",\"title\":\"Miles per Gallon\",\"type\":\"quantitative\"}}}"
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"Lab simple"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Well, that's disappointing. If you view the console where the `ihaskell-lab` output is going then line 20 caused the following message to be displayed:\n",
"\n",
"```\n",
"[W 2021-06-22 09:50:03.931 ServerApp] 404 GET /files/%7B%22mark%22%3A%7B%22tooltip%22%3A%7B%22content%22%3A%22encoding%22%7D%2C%22type%22%3A%22circle%22%7D%2C%22data%22%3A%7B%22url%22%3A%22https%3A/vega.github.io/vega-datasets/data/cars.json%22%7D%2C%22%24schema%22%3A%22https%3A/vega.github.io/schema/vega-lite/v4.json%22%2C%22encoding%22%3A%7B%22color%22%3A%7B%22field%22%3A%22Origin%22%7D%2C%22x%22%3A%7B%22field%22%3A%22Horsepower%22%2C%22type%22%3A%22quantitative%22%7D%2C%22y%22%3A%7B%22field%22%3A%22Miles_per_Gallon%22%2C%22title%22%3A%22Miles%20per%20Gallon%22%2C%22type%22%3A%22quantitative%22%7D%7D%7D?_xsrf=2%7C98ce9462%7C3d3b4c457dd3c91b64c7c45ee654fe34%7C1623793678 (127.0.0.1) 3.38ms referer=http://localhost:8888/lab/tree/hvega.ipynb\n",
"```\n",
"\n",
"What I believe is happening is that `vegalite string-encoded-JSON-value` treats the value as JSON via the following (i.e. we convert back from the string to the Aeson `Value`):\n",
"\n",
"```haskell\n",
"displayDataToJson (DisplayData MimeVegalite dataStr) =\n",
" pack (show MimeVegalite) .= fromMaybe (String \"\") (decodeStrict (Text.encodeUtf8 dataStr) :: Maybe Value)\n",
"```\n",
"\n",
"but the custom mimetype payload is treated as just a string with:\n",
"\n",
"```haskell\n",
"displayDataToJson (DisplayData mimeType dataStr) =\n",
" pack (show mimeType) .= String dataStr\n",
"```\n",
"\n",
"So **I think** we need some way for a user of the custom mimetype to be able to control how the payload is converted to the `(mimetype, output)` pair.\n",
"\n",
"Fortunately, as I said, I don't think that's a problem for me at the moment, but may be with the Vega-Lite version 5 schema. Unfortunately finding out what mimetypes are supported/used in Jupyter is not easy - https://jupyter.readthedocs.io/en/latest/reference/mimetype.html is not helpful and the rabbit-hole is too large for me just now."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"mimetype": "text/x-haskell",
"name": "haskell",
"pygments_lexer": "Haskell",
"version": "8.10.4"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment