{-# LANGUAGE OverloadedStrings #-}--------------------------------------------------------------------------------moduleData.Base64(encode)where--------------------------------------------------------------------------------importData.Bits(shiftL,shiftR,(.|.))importqualifiedData.ByteStringasBSimportqualifiedData.ByteString.LazyasLBSimportData.Word(Word32,Word8)--------------------------------------------------------------------------------tbl::BS.ByteStringtbl="ABCDEFGHIJKLMNOPQRSTUVWXYZ\
\abcdefghijklmnopqrstuvwxyz\
\0123456789+/"pad::Word8pad=61-- '='encode::LBS.ByteString->LBS.ByteStringencode=aux(Nothing,Nothing,Nothing)whereauxbufbs|""==bs=let(x,y,z)=casebufof(Justx',Justy',Nothing)->(x',y',0)(Justx',Nothing,Nothing)->(x',0,0)___________________________->(0,0,0)(a,b,c,d)=b64xyzinconsa$consb$consc$consd$""|otherwise=casebuf'of(Justx,Justy,Justz)->let(a,b,c,d)=b64xyzinconsa$consb$consc$consd$auxbuf'$tlbs________________________->auxbuf'$tlbswhereb64abc=letos=w32a.<.16.|.w32b.<.08.|.w32cin(idxtbl$int$os.>.18,idxtbl$int$os.<.14.>.26,ifb==0thenpadelseidxtbl$int$os.<.20.>.26,ifc==0thenpadelseidxtbl$int$os.<.26.>.26)buf'=casebufof(Nothing,b,c)->(Just$hdbs,b,c)(a,Nothing,c)->(a,Just$hdbs,c)(a,b,Nothing)->(a,b,Just$hdbs)(_,_,_)->(Just$hdbs,Nothing,Nothing)(.<.)xy=x`shiftL`y(.>.)xy=x`shiftR`yw32::Word8->Word32w32=fromIntegralint::Word32->Intint=fromIntegral-- O(1) ByteString index (subscript) operator, starting from 0.idx=BS.index-- O(1) cons is analogous to '(:)' for lists.cons=LBS.cons-- O(1) Extract the first element of a ByteString.hd=LBS.head-- O(1) Extract the elements after the head of a ByteString.tl=LBS.tail
#!/usr/bin/envstack{- stack
--resolver lts-12.0
--install-ghc
script
--package bytestring
--package hspec
--ghc-options -threaded
--ghc-options -Werror
--ghc-options -Wall
--
-}--------------------------------------------------------------------------------{-# LANGUAGE OverloadedStrings #-}--------------------------------------------------------------------------------moduleMain(main)where--------------------------------------------------------------------------------importqualifiedData.ByteString.LazyasLBSimportTest.HspecimportqualifiedData.Base64asBase64--------------------------------------------------------------------------------dec::LBS.ByteStringenc::LBS.ByteStringmain::IO()--------------------------------------------------------------------------------dec="Man is distinguished, not only by his reason, but by this singular \
\passion from other animals, which is a lust of the mind, that by a \
\perseverance of delight in the continued and indefatigable generation \
\of knowledge, exceeds the short vehemence of any carnal pleasure."enc="TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1\
\dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3\
\aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFu\
\Y2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxl\
\IGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhl\
\bWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="main=hspec$dodescribe("Base64 encode")$doit("https://en.wikipedia.org/wiki/B64enc#Examples")$(Base64.encodedec)`shouldBe`enc
user@personal:~/.../base64$ ./Test.hs
Base64 encode
https://en.wikipedia.org/wiki/B64enc#Examples
Finished in 0.0025 seconds
1 example, 0 failures
Profiling Snippet
profiling.bash
#!/bin/bash# base: downloads.haskell.org/~ghc/latest/docs/html/users_guide/# file: profiling.html#rts-flag--po%20%E2%9F%A8stem%E2%9F%A9
clear
# base64 (+ profiling)
ghc -prof-fprof-auto-rtsopts-Wall-Werror-O2--make Main.hs -obase64# clean
find .-name'*.hi'-delete
find .-name'*.o'-delete# run and generate process and memory profilescat ./misc/don_quijote.txt | \
./base64 +RTS -p-h> ./misc/don_quijote.b64
# create a graph of memory profile
hp2ps -c base64.hp
base64.aux
user@personal:~/.../base64$ cat base64.aux
X_RANGE 1.40
Y_RANGE 89416.00
ORDER MAIN 1
ORDER (235)GHC.Conc.Signal.CAF 2
ORDER (219)GHC.IO.Encoding.CAF 3
ORDER (209)GHC.IO.Handle.FD.CAF 4
ORDER (132)PINNED 5
SHADE MAIN 0.00
SHADE (235)GHC.Conc.Signal.CAF 0.00
SHADE (219)GHC.IO.Encoding.CAF 0.00
SHADE (209)GHC.IO.Handle.FD.CAF 0.00
SHADE (132)PINNED 0.10