Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active April 20, 2020 23:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenwebb/7eea6b043213653408b492f6a2de329c to your computer and use it in GitHub Desktop.
Save kenwebb/7eea6b043213653408b492f6a2de329c to your computer and use it in GitHub Desktop.
Haskell - Hutton - Binary string transmitter
<?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