Last active
April 20, 2020 23:17
-
-
Save kenwebb/7eea6b043213653408b492f6a2de329c to your computer and use it in GitHub Desktop.
Haskell - Hutton - Binary string transmitter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Mon Apr 20 2020 19:16:53 GMT-0400 (Eastern Daylight Time)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: Haskell - Hutton - Binary string transmitter | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 7eea6b043213653408b492f6a2de329c | |
Keywords: | |
My Notes | |
-------- | |
February 25, 2020 | |
In this workbook, I implement the "Binary string transmitter" in section 7.6 of the Hutton Haskell book [ref 1]. | |
I will experiment with different ways of implementing it using Xholon, using functional approaches. | |
My goal is to learn more about functional programming, starting from a place that I already understand. | |
http://127.0.0.1:8888/Xholon.html?app=Haskell+-+Hutton+-+Binary+string+transmitter&src=lstr&gui=clsc&jslib=ramda.min | |
February 26, 2020 | |
I have implemented it using a single node in Xholon + JavaScript + Ramda. | |
April 20, 2020 | |
There are now three versions of the same system: | |
- Haskell | |
- Raamda | |
- Formality-Lang | |
Haskell code from the Hutton book | |
--------------------------------- | |
-- Binary string transmitter example from chapter 7 of Programming | |
-- in Haskell, Graham Hutton, Cambridge University Press, 2016. | |
import Data.Char | |
-- Base conversion | |
type Bit = Int | |
bin2int :: [Bit] -> Int | |
bin2int = foldr (\x y -> x + 2*y) 0 | |
int2bin :: Int -> [Bit] | |
int2bin 0 = [] | |
int2bin n = n `mod` 2 : int2bin (n `div` 2) | |
make8 :: [Bit] -> [Bit] | |
make8 bits = take 8 (bits ++ repeat 0) | |
-- Transmission | |
encode :: String -> [Bit] | |
encode = concat . map (make8 . int2bin . ord) | |
chop8 :: [Bit] -> [[Bit]] | |
chop8 [] = [] | |
chop8 bits = take 8 bits : chop8 (drop 8 bits) | |
decode :: [Bit] -> String | |
decode = map (chr . bin2int) . chop8 | |
transmit :: String -> String | |
transmit = decode . channel . encode | |
channel :: [Bit] -> [Bit] | |
channel = id | |
References | |
---------- | |
(1) "Programming in Haskell, second edition" book, by Graham Hutton | |
(2) https://gist.github.com/kenwebb/ada78df446ce73c0a0e403b6e1079eac | |
Programming with Categories (DRAFT) - 1.1 Programming: the art of composition | |
in this previous workbook, I have experimented with ways to compose two functions, using Xholon and using Xholon with Ramda | |
(3) https://ramdajs.com/ | |
Ramda | |
A practical functional library for JavaScript programmers. | |
() https://gist.github.com/kenwebb/1d462a82bdb0577946b46f55f870ca28 | |
my version of a translation of transmit.hs | |
original source code: https://gist.github.com/johnchandlerburnham/efeccd2c038ce975813e34c9ca46777d | |
]]></Notes> | |
<_-.XholonClass> | |
<PhysicalSystem/> | |
<RamdaTest3/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
</xholonClassDetails> | |
<PhysicalSystem> | |
<RamdaTest3 roleName="THREEE Trying to be more point-free."/> | |
</PhysicalSystem> | |
<RamdaTest3behavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
const dotesting = false; | |
var me, | |
R, | |
take8, drop8, zero8, | |
bin2int, make8, int2bin, int2binRecurse, ord, chr, concat, encode, chop8, chop8Recurse, decode, transmit, channel, | |
parent, first, last, next, prev, btparent, btleft, btright, remove, id, name, role, val, text, obj, port, links, color, | |
log, println, print, | |
beh = { | |
postConfigure: function(msg) { | |
me = this.cnode; | |
R = null; | |
if ($wnd.R) { | |
R = $wnd.R; | |
take8 = R.take(8); | |
drop8 = R.drop(8); | |
zero8 = R.repeat(0, 8); | |
this.makeFunctions(); | |
this.makeXhFunctions(); | |
} | |
else { | |
me.println("THREE Ramda R is not available."); | |
} | |
}, | |
act: function() { | |
if (R) { | |
if (dotesting) { | |
me.println(bin2int([1,0,1,1])); | |
me.println(make8([1,0,1,1])); | |
me.println(int2bin(13)); | |
me.println(ord('a')); | |
me.println(chr(97)); | |
var result2 = R.compose(make8, int2bin, ord)('a'); | |
me.println(result2); | |
var funk = function(c) { | |
return R.compose(make8, int2bin, ord)(c) | |
}; | |
var inarr = "abc".split(""); | |
var result3 = inarr.map(funk); // an array of 3 arrays, where each sub-array has 8 integers | |
var result4 = concat(result3); | |
me.println(JSON.stringify(result4)); // [1,0,0,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,0,0,0,1,1,0] | |
me.println("ENCODE"); | |
me.println(JSON.stringify(encode("abc def"))); | |
var result5 = chop8(result4); | |
me.println(JSON.stringify(result5)); // | |
var result6 = decode(result4); | |
me.println(result6); | |
} | |
var txtext = R.pipe(parent, role)(me); | |
var result7 = transmit(txtext || "Hello World!"); | |
me.println(result7); | |
if (dotesting) { | |
me.println("RESULT10"); | |
var result10 = R.flatten(R.map(R.compose(make8, int2bin, ord), R.splitEvery(1, "abcdefg"))) | |
// how to make this point-free ??? | |
me.println(JSON.stringify(result10)); | |
me.println(result10.length); | |
// test log, println, print | |
var data = [9,8,7,6]; | |
//me.println(data); | |
log("LOG: ", data); | |
println("PRINTLN: ", data); | |
print("PRINT: ", data); | |
print("", "\n"); | |
// memoize | |
me.println(mmzxpath(me, "..")); | |
me.println(mmzxpath(me, "../..")); | |
me.println(mmzxpath(me, "../../*")); | |
me.println(mmzxpath(me, "../../RamdaTest2")); | |
} | |
} | |
}, | |
makeFunctions: function() { | |
// bin2int :: [Bit] -> Int | |
bin2int = R.reduceRight((x, y) => x + 2*y, 0) | |
// make8 :: [Bit] -> [Bit] | |
make8 = R.compose(take8, R.flip(R.concat)(zero8)) | |
// int2bin :: Int -> [Bit] | |
int2bin = n => R.equals(n,0) ? [] : R.prepend(R.modulo(n,2), int2bin(Math.floor(R.divide(n,2)))) | |
// ord :: Char -> Int | |
ord = c => c.charCodeAt() | |
// chr :: Int -> Char | |
chr = n => String.fromCharCode(n) | |
// concat :: [[Bit]] -> [Bit] | |
concat = arr => arr.flat() | |
// encode :: String -> [Bit] | |
encode = str => concat(str.split("").map(R.compose(make8, int2bin, ord))) | |
// chop8 :: [Bit] -> [[Bit]] | |
chop8 = bits => R.isEmpty(bits) ? [] : R.prepend(take8(bits), chop8(drop8(bits))) | |
// decode :: [Bit] -> String | |
decode = R.compose(R.join(""), R.map(R.compose(chr, bin2int)), chop8) | |
// channel :: [Bit] -> [Bit] | |
channel = R.identity | |
// transmit :: String -> String | |
transmit = R.compose(decode, channel, encode) | |
}, // end makeFunctions() | |
// ################################################################# | |
// make Xholon functions | |
makeXhFunctions: function() { | |
// ----------------------------------------------------------------- | |
// parent :: IXholon -> IXholon | |
parent = node => node.parent() | |
// first :: IXholon -> IXholon | |
first = node => node.first() | |
// last :: IXholon -> IXholon | |
last = node => node.last() | |
// next :: IXholon -> IXholon | |
next = node => node.next() | |
// prev :: IXholon -> IXholon | |
prev = node => node.prev() | |
// btparent :: IXholon -> IXholon | |
btparent = node => node.btparent() | |
// btleft :: IXholon -> IXholon | |
btleft = node => node.btleft() | |
// btright :: IXholon -> IXholon | |
btright = node => node.btright() | |
// remove :: IXholon -> IXholon | |
remove = node => node.remove() | |
// id :: IXholon -> Number | |
id = node => node.id() | |
// name :: IXholon -> String | |
name = node => node.name() | |
// role :: IXholon -> String | |
role = node => node.role() | |
// val :: IXholon -> Number | |
val = node => node.val() | |
// text :: IXholon -> String | |
text = node => node.text() | |
// obj :: IXholon -> Object | |
obj = node => node.obj() | |
// port :: (Number, IXholon) -> IXholon | |
port = (portNum, node) => node.port(portNum) | |
// links :: (Boolean, Boolean, IXholon) -> [PortInformation] | |
links = (placeGraph, linkGraph, node) => node.links(placeGraph, linkGraph) | |
// color :: IXholon -> String | |
color = node => node.color() | |
// tick :: IXholon -> Object -> Object | |
tick = (node, obj) => node.tick(obj) | |
// ex: log("current data", [1,2,3,4]) | |
log = function(str, data) {console.log(str + data); return data;} | |
// ex: println("current data: ", [1,2,3,4]) | |
println = function(str, data) {const node = $wnd.xh.root(); node.println(str + data); return data;} | |
// ex: print("current data: ", [1,2,3,4]) | |
print = function(str, data) {const node = $wnd.xh.root(); node.print(str + data); return data;} | |
// memoize xpath | |
mmzxpath = (node, xpathExpr) => { | |
const cache = {}; | |
const argStr = node.name() + xpathExpr; | |
cache[argStr] = cache[argStr] || node.xpath(xpathExpr); | |
return cache[argStr]; | |
} | |
} // end makeXhFunctions() | |
} // end beh | |
//# sourceURL=RamdaTest3behavior.js | |
]]></RamdaTest3behavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>RamdaTest</title> | |
<rect id="PhysicalSystem/RamdaTest3" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
<g> | |
<title>behavior</title> | |
<rect id="PhysicalSystem/RamdaTest/RamdaTest3behavior" fill="#6AB06A" height="50" width="10" x="80" y="0"/> | |
</g> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment