Constraint Functional-Logic Programming

This module provides an interface that can be used for constraint functional-logic programming in Haskell.

{-# LANGUAGE
GeneralizedNewtypeDeriving,
MultiParamTypeClasses,
FlexibleInstances,
FlexibleContexts,
TypeFamilies,
RankNTypes
#-}

module CFLP (

CFLP, Enumerable(..), Ctx, Data, Computation,

eval, evalPartial, evalPrint,

Monadic, monadic, UpdateT,

module CFLP.Data

) where

import Control.Monad.State

import CFLP.Data
import CFLP.Data.Types

import CFLP.Control.Monad.Update

import CFLP.Control.Strategy

The type class CFLP amalgamates all class constraints on constraint functional-logic computations.

class (Strategy (Ctx s) s, MonadPlus s
, MonadUpdate (Ctx s) s
, Update (Ctx s) s s
, Update (Ctx s) s (Res s)
, MonadPlus (Res s)
, Enumerable (Res s))
=> CFLP s

monadic :: Monad m => Monadic (UpdateT c m) ()
monadic = Monadic (return ())

instance (MonadPlus m, Enumerable m) => CFLP (Monadic (UpdateT () m))

We define a shortcut for types of constraint functional-logic data and computations that can be parameterized by an arbitrary strategy.

type Data s a = Nondet (Ctx s) s a

type Computation a
= forall s . CFLP s => Context (Ctx s) -> ID -> Data s a

We provide

eval, evalPartial
:: (Monad s, CFLP s, Generic a) => [s (Ctx s)] -> Computation a -> IO [a]
eval s = liftM (liftM primitive) . evaluate s groundNormalForm
evalPartial s = liftM (liftM primitive) . evaluate s partialNormalForm

evalPrint :: (Monad s, CFLP s, Generic a)
=> [s (Ctx s)] -> Computation a -> IO ()
evalPrint s op = evaluate s partialNormalForm op >>= printSols

printSols :: Show a => [a] -> IO ()
printSols [] = putStrLn "No more solutions."
printSols (x:xs) = do
print x
putStr "more? [Y(es)|n(o)|a(ll)]: "
s <- getLine
if s `elem` ["n","no"] then
return ()
else if s `elem` ["a","all"]
then mapM_ print xs
else printSols xs

The evaluate function enumerates the non-deterministic solutions of a constraint functional-logic computation according to a given strategy.

evaluate :: CFLP s
=> [s (Ctx s)]
-> (s (Ctx s) -> Nondet (Ctx s) s a -> Res s b)
-> Computation a
-> IO [b]
evaluate s evalNondet op = do
i <- initID
return $ concatMap enumeration $
map (\c -> evalNondet c (Typed (c >>= untyped . flip op i . Context))) s