Skip to content

Calling Fay from JavaScript

Adam Bergmark edited this page Sep 15, 2013 · 6 revisions

Fay 0.18 (not yet on hackage, but feel free to try out the master branch!) introduces the possibility to automatically generate wrappers for modules that can be used to call Fay from JavaScript. This was possible to do manually before, but it was very verbose and error-prone.

Here's an example, a Vector library that we want to write in Fay but use from JavaScript, this is available in the repository under examples/FayFromJs.hs

module FayFromJs where

import           Prelude

data Vector = Vector { x :: Double , y :: Double }

aVector :: Vector
aVector = Vector 1 2

len :: Vector -> Double
len (Vector a b) = sqrt (a^^2 + b^^2)

add :: Vector -> Vector -> Vector
add (Vector a b) (Vector c d) = Vector (a+c) (b+d)

Compile this with fay examples/FayFromJs.hs --strict FayFromJs. For each export in FayFromJs This will generate a wrapped version, such as Strict.FayFromJs.add. Here's how we could use this from JavaScript:

function print(label, v)
{
  var div = document.createElement("div");
  div.innerHTML = label + JSON.stringify(v);
  document.body.appendChild(div);
}

window.onload = function () {
  var V = Strict.FayFromJs;
  // Constant
  print("aVector = ", V.aVector); // =>  {"x":1,"y":2}
  // Simple function calls
  print("|aVector| = ", V.len(V.aVector)); // => 2.23606797749979
  // Arguments are deserialized from JSON using Automatic.
  print("|[10, 20]| = ", V.len({ instance : "Vector", x : 10, y : 20 })); // => 22.360679774997898
  // Call with uncurried arguments
  // Return values are serialized to the JSON format using Automatic.
  print( "aVector + [10, 20] = "
       , V.add(V.aVector, { instance : "Vector", x : 10, y : 20 })); // => {"instance":"Vector","x":11,"y":22}
  // Curried call is also fine
  print( "aVector + [10, 20] = "
       , V.add(V.aVector)({ instance : "Vector", x : 10, y : 20 })); // => {"instance":"Vector","x":11,"y":22}
};