Cow Description Language (CDL)
In times of the pandemic, it's not easy to get real input data from your cows to demonstrate the functionality of your front end. To be able to test some features of the application, we would like to have scripts that insert fake data points into our database, allowing us how our app would behave in real time, without the need to hook up any collars. These scripts would be tedius to write...
Unless, of course, you have a Domain Specific Language (DSL) for it! Enter CDL. We can describe a cow in a turtle-style imperative language:
squareCow = do move 10 turn 90 move 10 turn 90 move 10 turn 90 move 10
This DSL is shallowly embedded into Haskell, which means that we can use all of Haskell's abstraction capabilities:
repeat 0 _ = return () repeat n thing = do thing repeat (n-1) thing squareCow = repeat 4 $ do move 10 turn 90
Given a sampling frequency, CDL can generate a Python script that inserts data points into our database each "sample":
from server.fgs.model import * from server.fgs import db import datetime db.session.add(DataPoint(longitude=0.0, latitude=0.0, datetime=datetime.now())) db.session.commit() sleep(0.1) db.session.add(DataPoint(longitude=9.0000094e-7, latitude=0.0, datetime=datetime.now())) db.session.commit() sleep(0.1) db.session.add(DataPoint(longitude=1.8000019e-6, latitude=0.0, datetime=datetime.now())) db.session.commit() sleep(0.1) # ...
To generate scripts, load the program into GHCI and execute as follows:
cd src ghci :load Cdl/SampleCows.hs Cdl/Codegen.hs Cdl/Cow.hs :module Cdl.SampleCows Cdl.Codegen Cdl.Cow outputCow "test.py" 0.1 (1, 1, Coord 0 0, squareCow)
0.1 is the sampling frequency (how often
the database will receive mock data from the cows), the first
the collar ID sending the data, the second
1 is the cow's walking speed (in meters/second),
Coord 0 0 is the initial longitude and latitude of the cow, and
the cow's actions described above.
Note that the script relies on being in the same directory as the
containing our database model.