-
-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proof of concept for higher-order DSL API #36
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
{-# LANGUAGE UndecidableInstances, UndecidableSuperClasses, FlexibleContexts #-} | ||
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, DerivingVia, ScopedTypeVariables #-} | ||
{-# LANGUAGE PolyKinds, TypeFamilyDependencies #-} | ||
{-# LANGUAGE FunctionalDependencies, TypeApplications #-} | ||
{-# OPTIONS_GHC -Wno-redundant-constraints #-} | ||
|
||
{-| This module provides an experimental DSL for generating Souffle Datalog code, | ||
|
@@ -92,6 +93,7 @@ module Language.Souffle.Experimental | |
, __ | ||
, underscore | ||
, (|-) | ||
, (||-) | ||
, (\/) | ||
, not' | ||
-- ** Souffle operators | ||
|
@@ -477,6 +479,18 @@ Head name terms |- body = | |
|
||
infixl 0 |- | ||
|
||
(||-) | ||
:: forall a k prog. (GenVars (Structure a), ToFun (MapType (Term 'Relation) (Structure a)) (Body 'Relation ()) k) | ||
=> Predicate a | ||
-> k | ||
-> DSL prog 'Definition () | ||
(Predicate h) ||- f = h vars |- applyFun (Proxy @(MapType (Term 'Relation) (Structure a))) f vars | ||
where | ||
vars :: Tuple 'Relation (Structure a) | ||
vars = genVars (Proxy @(Structure a)) | ||
|
||
infixl 0 ||- | ||
|
||
-- | A typeclass used for generating AST fragments of Datalog code. | ||
-- The generated fragments can be further glued together using the | ||
-- various functions in this module. | ||
|
@@ -991,6 +1005,24 @@ accessorNames _ = case toStrings (Proxy :: Proxy (AccessorNames a)) of | |
-- Only tuples containing up to 10 elements are currently supported. | ||
type Tuple ctx ts = TupleOf (MapType (Term ctx) ts) | ||
|
||
class GenVars (ts :: [Type]) where | ||
genVars :: Proxy ts -> Tuple 'Relation ts | ||
|
||
varI :: Int -> Term 'Relation a | ||
varI i = VarTerm $ "x" <> T.pack (show i) | ||
|
||
instance GenVars '[t] where | ||
genVars _ = varI 0 | ||
|
||
instance GenVars '[t1, t2] where | ||
genVars _ = (varI 0, varI 1) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sucks big-time. It should be an inductive definition, instead of requiring separate instances for each tuple length. Also, it should run in one of your variable number-tracking monads, but I decided that life's too short to worry about that for this illustration. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, tuples are really annoying to work with in Haskell :( main reason I used them is to keep the syntax the same as in Datalog. For now I limited it to 10 instances which is kinda "meh", but it gets the job done. If you know a better way of handling raw tuples in combination with typeclasses, let me know! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well the straightforward way would be to use an You could carry a list of types everywhere, and convert to a Haskell tuple at the last minute, but that becomes unwieldy on the way back I think -- because of one-tuples, you can't easily have a bijection between
and
|
||
class ToFun (ts :: [Type]) r k | ts r -> k where | ||
applyFun :: Proxy ts -> k -> TupleOf ts -> r | ||
|
||
instance ToFun '[] r r | ||
instance (ToFun ts r k) => ToFun (t:ts) r (t -> k) | ||
|
||
class ToTerms (ts :: [Type]) where | ||
toTerms :: Proxy ctx -> TypeInfo a ts -> Tuple ctx ts -> NonEmpty SimpleTerm | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming is hard, let's go shopping!
I think if this is finished, you can just use
|-
for the new one, and get rid of the old one everywhere.