packages feed

aern2-mp-0.2.15.0: src/AERN2/Select.hs

{-|
    Module      :  AERN2.Select
    Description :  multivalued select operation
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable

    Generic multivalued select operation
-}
module AERN2.Select where

import MixedTypesNumPrelude

import qualified Numeric.CollectErrors as CN

import AERN2.Kleenean

class (IsBool (SelectType k)) => CanSelect k where
  {-| Must be Bool or similar -}
  type SelectType k 
  {-|
    Execute two lazy computations "in parallel" until one of them succeeds. 
  -}
  select :: k -> k -> (SelectType k) {-^ True means that the first computation succeeded. -}

type CanSelectBool k = (CanSelect k, SelectType k ~ Bool)
type CanSelectCNBool k = (CanSelect k, SelectType k ~ CN Bool)

instance CanSelect Kleenean where
  type SelectType Kleenean = CN Bool
  select CertainTrue _ = cn True
  select _ CertainTrue = cn False
  select CertainFalse CertainFalse =
    CN.noValueNumErrorPotential $ 
      CN.NumError "select (Kleenean): Both branches failed!"
  select _ _ = 
    CN.noValueNumErrorPotential $ 
      CN.NumError "select (Kleenean): Insufficient information to determine selection."

instance CanSelect (CN Kleenean) where
  type SelectType (CN Kleenean) = CN Bool
  select cnk1 cnk2 =
    do
    k1 <- cnk1
    k2 <- cnk2
    select k1 k2

class CanSelectCountable k where
  {-| Must be Integer or similar -}
  type SelectCountableType k 
  {-|
    Execute a sequence of lazy computations "in parallel" until one of them succeeds
    and return the index of a succeeding computation. 
  -}
  selectCountable :: (Integer -> k) -> SelectCountableType k

type CanSelectCountableInteger k = (CanSelectCountable k, SelectCountableType k ~ Integer)
type CanSelectCountableCNInteger k = (CanSelectCountable k, SelectCountableType k ~ CN Integer)

instance CanSelectCountable Kleenean where
  type SelectCountableType Kleenean = Integer
  selectCountable kleeneans = aux 0
    where
    aux i = case kleeneans i of
      CertainTrue -> i
      _ -> aux (i + 1)

instance CanSelectCountable (CN Kleenean) where
  type SelectCountableType (CN Kleenean) = CN Integer
  selectCountable cnkleeneans = aux 0
    where
    aux i = do
      ki <- cnkleeneans i
      case ki of
        CertainTrue -> cn i
        _ -> aux (i + 1)