Get the code:
git clone https://github.com/alephcloud/bayhac2014
cd bayhac2014
Build Haste:
cabal sandbox init
echo 'constraints: scientific<0.3' >> cabal.config
cabal install haste-compiler -j
export PATH=./.cabal-sandbox/bin:$PATH
Setup Haste:
echo 'solver: topdown' >> ~/.cabal/config
haste-boot
sed -i '/solver: topdown/d' ~/.cabal/config
Setup and usage of Haste
Development of portable libraries for web applications
git clone https://github.com/alephcloud/bayhac2014
git clone https://github.com/alephcloud/bayhac2014
cabal install haste-compiler
haste-boot
well ...
echo 'constraints: scientific<0.3' >> cabal.config
cabal install haste-compiler
echo 'solver: topdown' >> ~/.cabal/config
haste-boot
sed -i '/solver: topdown/d' ~/.cabal/config
git clone https://github.com/alephcloud/bayhac2014
contrib/hello-bayhac.hs
:
module Main
( main
) where
import Haste
main :: IO ()
main = alert "hello bayhac"
Compile:
hastec hello-bayhac.hs
contrib/hello-bayhac.html
:
<!DOCTYPE html>
<html>
<head> <script type="text/javascript" src="./hello-bayhac.js"></script></head>
<body/>
</html>
git clone https://github.com/alephcloud/bayhac2014
Thunks:
function T(f) {
this.f = new F(f);
}
function F(f) {
this.f = f;
}
Evaluate to head normal form:
function E(t) { /* ... */ }
Partial application:
function A(f, args) { /* ... */ }
git clone https://github.com/alephcloud/bayhac2014
toJSStr
, fromJSStr
jsAlert
, jsPrompt
, jsLog
, jsEval
, etc.jsSetTimeout
git clone https://github.com/alephcloud/bayhac2014
contrib/hello-bayhac.hs
:
module Main
( main
) where
import Haste
main :: IO ()
main = alert "hello bayhac"
Result:
var _0=0,
_1=unCStr("hello bayhac"),
_2=function(_){var _3=jsAlert(toJSStr(E(_1)));return _0;},
_4=function(_){return _2(_);};
var hasteMain = function() {A(_4, [0]);};
window.onload = hasteMain;
git clone https://github.com/alephcloud/bayhac2014
[<Constructor ID>, <Constructor Args>, ...]
Examples:
Haskell | Javascript |
---|---|
5 :: Int
|
[0,5]
|
Nothing :: Maybe ()
|
[0,[0]]
|
Just () :: Maybe ()
|
[1,[0]]
|
[1,2] :: [Int]
|
[1,[0,1],[1,[0,2],[0]]]
|
git clone https://github.com/alephcloud/bayhac2014
Example code from the Haste runtime:
function arr2lst(arr, elem) {
if(elem >= arr.length) {
return [0];
}
return [1, toHS(arr[elem]), new T(function() {return arr2lst(arr,elem+1);})]
}
function lst2arr(xs) {
var arr = [];
for(; xs[0]; xs = E(xs[2])) {
arr.push(E(xs[1]));
}
return arr;
}
git clone https://github.com/alephcloud/bayhac2014
Static:
foreign import ccall "alert" alert2 :: JSString -> IO ()
Dynamic:
alert3 :: JSString -> IO ()
alert3 = ffi "(function(x) { alert(x); })"
git clone https://github.com/alephcloud/bayhac2014
module Main
( main
) where
import Haste
import Haste.Prim
import Haste.Foreign
foreign import ccall "alert" alert2 :: JSString -> IO ()
alert3 :: JSString -> IO Int
alert3 = ffi "(function (x) { alert(x); return 0; })"
foreign import ccall "setTimeout" timeout :: JSFun (IO ()) -> Int -> IO ()
main :: IO ()
main = do
alert2 $ toJSStr "hello bayhac 2"
alert3 $ toJSStr "hello bayhac 3"
flip timeout 2000 . mkCallback . alert2 . toJSStr $ "hello bayhac 4"
git clone https://github.com/alephcloud/bayhac2014
git clone https://github.com/alephcloud/bayhac2014
A very simple encryption library.
A very simple web email encryption application.
Code:
git clone https://github.com/alephcloud/bayhac2014
cabal install --enable-tests
cabal test
Result:
git clone https://github.com/alephcloud/bayhac2014
newtype Password = Password { unPassword ∷ B.ByteString }
deriving (Eq, Code64)
newtype CipherText = CipherText { unCipherText ∷ B.ByteString }
deriving (Eq, Code64)
newtype PlainText = PlainText { unPlainText ∷ B.ByteString }
deriving (Eq, Code64)
encryptWithPwd ∷ Password → PlainText → IO CipherText
decryptWithPwd ∷ Password → CipherText → Either String PlainText
git clone https://github.com/alephcloud/bayhac2014
class (FromJSON α, ToJSON (Response α)) ⇒ Request α where
type Response α ∷ *
answerRequest ∷ α → IO (Either String (Response α))
data EncryptWithPwd = EncryptWithPwd
{ ePassword ∷ !Password
, ePlainText ∷ !PlainText
}
instance FromJSON EncryptWithPwd where
parseJSON = withObject "EncryptWithPwd" $ \o → EncryptWithPwd
<$> o .: "password"
<*> o .: "plain_text"
data EncryptWithPwdR = EncryptWithPwdR
{ erCipherText ∷ !CipherText
}
instance ToJSON EncryptWithPwdR where
toJSON EncryptWithPwdR{..} = object
[ "cipher_text" .= erCipherText
]
instance Request EncryptWithPwd where
type Response EncryptWithPwd = EncryptWithPwdR
answerRequest EncryptWithPwd{..} =
Right ∘ EncryptWithPwdR <$> encryptWithPwd ePassword ePlainText
git clone https://github.com/alephcloud/bayhac2014
rm -rf dist
haste-inst install
well ...
rm -rf dist
mv cabal.sandbox.config cabal.sandbox.config.disabled
haste-inst install -fhaste --dependencies-only
haste-inst configure -fhaste
haste-inst build
bayhac2014-cryptmail.cabal
:
...
ghc-options: -Wall --start=asap --with-js=lib/sjcl.js,lib/bayhac2014-cryptmail.js
...
git clone https://github.com/alephcloud/bayhac2014
Result: bayhac2014-cryptmail-app
var logg = function(str) { console.log(str); return; }
var api = new API();
var req = { "password" : btoa(pwd), "plain_text" : btoa(msg) };
api.encrypt_with_password(req, logg, logg, function (r) {
console.log(r.cipher_text);
}
var req = { "password" : btoa(pwd), "cipher_text" : msg };
api.decrypt_with_password(, logg, logg, function (r) {
console.log(r.plain_text);
}
The Javascript API exposes the service API
git clone https://github.com/alephcloud/bayhac2014
Examples:
Low-level dependencies:
Dispatch Options:
git clone https://github.com/alephcloud/bayhac2014
Flag haste
description: build with haste-compiler
default: False
Library
exposed-modules:
BayHac2014.Cryptmail.Text
BayHac2014.Cryptmail.ByteString
BayHac2014.Cryptmail.PasswordEncryption
BayHac2014.Cryptmail.ServiceApi
BayHac2014.Cryptmail.Json
if flag(haste)
build-depends: ...
else
build-depends: ...
Executable cryptmail-client
if ! flag(haste)
buildable: False
Executable cryptmail-server
if flag(haste)
buildable: False
git clone https://github.com/alephcloud/bayhac2014
newtype ByteString = ByteString JSAny
foreign import ccall "bsEmpty" j_bytesEmpty ∷ IO ByteString
foreign import ccall "bsConcat" j_bytesConcat ∷ ByteString → ByteString → IO ByteString
foreign import ccall "bsEqual" j_bytesEqual ∷ ByteString → ByteString → Bool
foreign import ccall "bsLength" j_bytesLength ∷ ByteString → Int
instance Monoid ByteString where
mempty = unsafePerformIO $ j_bytesEmpty
mappend a b = unsafePerformIO $ j_bytesConcat a b
{-# INLINE mempty #-}
{-# INLINE mappend #-}
instance Eq ByteString where
(==) a b = j_bytesEqual a b
{-# INLINE (==) #-}
length ∷ ByteString → Int
length = j_bytesLength
main ∷ IO ()
main = do
register "encrypt_with_password" (asyncRequest ∷ ApiMethod EncryptWithPwd)
register "decrypt_with_password" (asyncRequest ∷ ApiMethod DecryptWithPwd)
-- -------------------------------------------------------------------------- --
type ApiMethod α
= α -- ^ argument
→ (JSString → IO ()) -- ^ log callback
→ (JSString → IO ()) -- ^ failure callback
→ (Response α → IO ()) -- ^ success callback
→ IO ()
register ∷ (FromJSON α, ToJSON (Response α)) ⇒ JSString → ApiMethod α → IO ()
asyncRequest ∷ Request α ⇒ ApiMethod α
type FCallback
= Ptr Value -- ^ argument
→ Ptr (JSString → IO ()) -- ^ log method
→ Ptr (JSString → IO ()) -- ^ failure continuation
→ Ptr (Ptr Value → IO ()) -- ^ success continuation
→ IO ()
foreign import ccall "addApiMethod" js_add_api_method ∷ JSString → JSFun FCallback → IO ()
function API () {
return this;
}
API.prototype.addMethod = function (name, method) {
API.prototype[name] = function (arg, log, fail, succ) {
var successCB = function (hsResult) {
/* convert result from the Haste JSON representation into a Javascript Object */
}
/* parse the argument object into the Haste JSON representation */
/* call the method callback */
var mapply = function () { return A(method,[[0,hsArg],[0,log],[0,fail],[0,successCB],0]); };
setTimeout(mapply,0);
}
return 0;
}
function addApiMethod(name, method) {
API.prototype.addMethod(name, method);
}
function calls(f,s) { f(E(s)[1]); }
function callv(f,v) { f(v[1]); }
git clone https://github.com/alephcloud/bayhac2014
Value
git clone https://github.com/alephcloud/bayhac2014