<commit_before>import qualified Data.Map as M

data Database = Database {
						dmap :: (M.Map String [String])
					}

data Rule = Relation String String | Imply String String
	deriving(Show)
type Clause = [Rule]

main :: IO ()
main = do
	let c = emptyClause
	print $ query [
			(Relation "band" "bob"),
			(Relation "band" "tom"),
			(Relation "band" "pete"),
			(Imply "sit" "drummer"),
			(Relation "sit" "bob")
		] "drummer"

query :: Clause -> String -> [String]
query c s = ((M.! s) . dmap . compileClause) c

emptyClause :: Clause
emptyClause = []

compileClause :: Clause -> Database
compileClause = foldr evalRule db
	where
		db = Database M.empty

evalRule :: Rule -> Database -> Database
evalRule r (Database m) = Database (insertion m)
				where 
					insertion = case r of
						(Relation tar val) -> M.insertWith (++) tar [val]
						(Imply tar val) -> M.insertWith (++) val (m M.! tar)<commit_msg>dynamified the logic<commit_after>{-
More advanced example
band bob;
band tom;
band pete;

sit bob;

sit X -> drummer X;
band X -> love X groupie;

love X groupie and drummer X?
bob
-}

module Main where

import Data.Char(isUpper)
import Data.List(foldl')
import qualified Data.Map as M

data Database = Database {
						dmap :: (M.Map String [[String]])
					}

data Rule = Relation String [String] | Imply String [String] String [String]
	deriving(Show)
type Clause = [Rule]

main :: IO ()
main = do
	let c = emptyClause
	print $ query [
			(Relation "band" ["bob"]),
			(Relation "band" ["tom"]),
			(Relation "band" ["pete"]),
			(Relation "sit" ["bob"]),
			(Imply "sit" ["X"] "drummer" ["X"]),
			(Imply "band" ["X"] "love" ["X", "groupie"])
		] "love"

query :: Clause -> String -> [[String]]
query c s = ((M.! s) . dmap . compileClause) c

emptyClause :: Clause
emptyClause = []

compileClause :: Clause -> Database
compileClause = foldl' evalRule db
	where
		db = Database M.empty

evalRule :: Database -> Rule -> Database
evalRule (Database m) r = Database (insertion m)
				where 
					insertion = case r of
						(Relation tar vals) -> M.insertWith (++) tar [vals]
						(Imply tar ts val vs) -> M.insertWith (++) val $ 
							implifications (evalVariables ts (m M.! tar)) vs


-- This function provides the desired variable combinations.
evalVariables :: [String] -> [[String]] -> [[(String, String)]]
evalVariables vars rs = filter ((==length vars).length) $ map (go vars) rs
	where
		go [] [] = []
		go (v:vs) (r:rs) = if isUpper (head v)
								then (v, r):go vs rs
							else if v == r 
								then ("_", r): go vs rs
								else []

intersections :: [[(String, String)]] -> [[(String, String)]] -> [[String]]
intersections [] _ = []
intersections _ [] = []
intersections (xs:xss) (ys:yss) = [v1 | (n1, v1) <- xs, (n2, v2) <- ys, n1 == n2]:intersections xss yss

-- Calculates the set after implification.
implifications :: [[(String, String)]] -> [String] -> [[String]]
implifications [] _ = []
implifications (x:xs) ys = map go ys:implifications xs ys
					where
						go y 
							| isUpper $head y = match y x
							| otherwise = y
						match t [] = t
						match t ((n,v):ls) = if n == t then v else match t ls
{'fraction_non_alphanumeric': 0.15958121827411167, 'fraction_numerical': 0.002220812182741117, 'mean_word_length': 3.0841968911917097, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4161091', 'n_tokens_mistral': 1236, 'n_tokens_neox': 1075, 'n_words': 375}