packages feed

rec-def-0.1: Data/Recursive/Propagator/Class.hs

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}

-- | This module provides the 'Propagator' and 'HasPropagator' classes.
module Data.Recursive.Propagator.Class where

import Data.Monoid (Dual(..))
import qualified Data.Set as S
import Data.Coerce

import qualified Data.Recursive.Propagator.Naive as Naive
import Data.Recursive.Propagator.P2
import Data.POrder

-- | The Propagator class defines some functions shared by different propagator
-- implementations. This backs the generic "Data.Recursive.R.Internal" wrapper.
class Propagator p x | p -> x where
    -- | The type of values inside the propagator
    newProp :: IO p
    newConstProp :: x -> IO p
    readProp :: p -> IO x

instance Bottom x => Propagator (Naive.Prop x) x where
    newProp = Naive.newProp bottom
    newConstProp = Naive.newProp
    readProp = Naive.readProp

instance Propagator PBool Bool where
    newProp = coerce newP2
    newConstProp False = coerce newP2
    newConstProp True = coerce newTopP2
    readProp = coerce isTop

instance Propagator PDualBool (Dual Bool) where
    newProp = coerce newP2
    newConstProp (Dual True) = coerce newP2
    newConstProp (Dual False) = coerce newTopP2
    readProp = coerce $ fmap not . isTop

-- | The HasPropagator class is used to pick a propagator implementation for a
-- particular value type.
class Propagator (Prop x) x => HasPropagator x where
    type Prop x

instance HasPropagator Bool where
    type Prop Bool = PBool

instance HasPropagator (Dual Bool) where
    type Prop (Dual Bool) = PDualBool

instance Eq a => HasPropagator (S.Set a) where
    type Prop (S.Set a) = Naive.Prop (S.Set a)