Design question: configuring predicate via dhall file


(Kostiantyn Rybnikov) #1

Hi! I’ve recently made a minimalistic tool called trigger https://github.com/k-bx/trigger that would watch a file for a change, and kill/restart the process once it’s changed. Now, I wanted to make that tool a bit more configurable, and I thought that Dhall might be a great fit.

Configuration, as I see it, would be as simple as a predicate, which takes executable’s file path and event as parameters, and returns a Bool, deciding if restart is needed or not.

I’ve made this initially:

data Event
  = Added FPath
  | Modified FPath
  | Removed FPath
  | Unknown FPath
  deriving (Generic)

instance Interpret Event

instance Inject Event

data Options = Options
  { predicate :: Text -> Event -> Bool
  } deriving (Generic)

instance Interpret Options

The problem, thou, is that once I’ve tried to create self-rebuild.dhall looking like this:

{ predicate = \(path : Text) -> \(event : Event) -> True }

I’ve figured that I don’t see what would be a way to share the Event type I have in my Haskell code with my Dhall configuration.

Maybe I should look at the problem under a different angle.

Ideas are appreciated. Thank you!


(Gabriel Gonzalez) #2

This works:

-- ./self-rebuild.dhall

let Event =
      < Added :
          { _1 : Text }
      | Modified :
          { _1 : Text }
      | Removed :
          { _1 : Text }
      | Unknown :
          { _1 : Text }
      >

in  { predicate = λ(path : Text) → λ(event : Event) → True }
-- ./example.hs

{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE RecordWildCards   #-}
{-# LANGUAGE OverloadedStrings #-}

import Dhall

type FPath = Text

data Event
  = Added FPath
  | Modified FPath
  | Removed FPath
  | Unknown FPath
  deriving (Generic, Inject)

data Options = Options
  { predicate :: Text -> Event -> Bool
  } deriving (Generic, Interpret)

main :: IO ()
main = do
    Options {..} <- input auto "./self-rebuild.dhall"

    print (predicate "foo" (Modified "bar"))
$ runghc ./example.hs
True

In other words, if you marshal the Dhall function into Haskell then you can call it as many times as you want on Haskell Events. Under the hood, the Interpret instance for functions uses the Inject instance for the function’s arguments (i.e. Event in this case) to transparently marshal the function’s arguments into Dhall for you.