{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
module What4.LabeledPred
( LabeledPred(..)
, labeledPred
, labeledPredMsg
, partitionByPreds
, partitionByPredsM
, partitionLabeledPreds
) where
import Control.Lens
import Data.Bifunctor.TH (deriveBifunctor, deriveBifoldable, deriveBitraversable)
import Data.Data (Data)
import Data.Coerce (coerce)
import Data.Data (Typeable)
import Data.Eq.Deriving (deriveEq1, deriveEq2)
import Data.Foldable (foldrM)
import Data.Ord.Deriving (deriveOrd1, deriveOrd2)
import GHC.Generics (Generic, Generic1)
import Text.Show.Deriving (deriveShow1, deriveShow2)
import What4.Interface (IsExprBuilder, Pred, asConstantPred)
data LabeledPred pred msg
= LabeledPred
{
_labeledPred :: !pred
, _labeledPredMsg :: !msg
}
deriving (Eq, Data, Functor, Generic, Generic1, Ord, Typeable)
$(deriveBifunctor ''LabeledPred)
$(deriveBifoldable ''LabeledPred)
$(deriveBitraversable ''LabeledPred)
$(deriveEq1 ''LabeledPred)
$(deriveEq2 ''LabeledPred)
$(deriveOrd1 ''LabeledPred)
$(deriveOrd2 ''LabeledPred)
$(deriveShow1 ''LabeledPred)
$(deriveShow2 ''LabeledPred)
labeledPred :: Lens (LabeledPred pred msg) (LabeledPred pred' msg) pred pred'
labeledPred = lens _labeledPred (\s v -> s { _labeledPred = v })
labeledPredMsg :: Lens (LabeledPred pred msg) (LabeledPred pred msg') msg msg'
labeledPredMsg = lens _labeledPredMsg (\s v -> s { _labeledPredMsg = v })
partitionByPredsM ::
(Monad m, Foldable t, IsExprBuilder sym) =>
proxy sym ->
(a -> m (Pred sym)) ->
t a ->
m ([a], [a], [a])
partitionByPredsM _proxy getPred xs =
let step x (true, false, unknown) = getPred x <&> \p ->
case asConstantPred p of
Just True -> (x:true, false, unknown)
Just False -> (true, x:false, unknown)
Nothing -> (true, false, x:unknown)
in foldrM step ([], [], []) xs
partitionByPreds ::
(Foldable t, IsExprBuilder sym) =>
proxy sym ->
(a -> Pred sym) ->
t a ->
([a], [a], [a])
partitionByPreds proxy getPred xs =
runIdentity (partitionByPredsM proxy (coerce getPred) xs)
partitionLabeledPreds ::
(Foldable t, IsExprBuilder sym) =>
proxy sym ->
t (LabeledPred (Pred sym) msg) ->
([LabeledPred (Pred sym) msg], [LabeledPred (Pred sym) msg], [LabeledPred (Pred sym) msg])
partitionLabeledPreds proxy = partitionByPreds proxy (view labeledPred)