hasklepias 0.4.4 → 0.5.0
raw patch · 11 files changed
+132/−65 lines, 11 filesdep +witherablePVP ok
version bump matches the API change (PVP)
Dependencies added: witherable
API changes (from Hackage documentation)
- Hasklepias.Types.Feature: [getFeature] :: Feature d -> Either MissingReason d
- Hasklepias.Types.Feature: instance GHC.Base.Functor Hasklepias.Types.Feature.Feature
- Hasklepias.Types.Feature: instance GHC.Classes.Eq d => GHC.Classes.Eq (Hasklepias.Types.Feature.Feature d)
- Hasklepias.Types.Feature: instance GHC.Generics.Generic (Hasklepias.Types.Feature.Feature d)
- Hasklepias.Types.Feature: instance GHC.Show.Show d => GHC.Show.Show (Hasklepias.Types.Feature.Feature d)
- Hasklepias.Types.Feature: newtype Feature d
- Hasklepias.Types.Feature.Aeson: instance Data.Aeson.Types.ToJSON.ToJSON d => Data.Aeson.Types.ToJSON.ToJSON (Hasklepias.Types.Feature.Feature d)
+ Hasklepias.Reexports: (++) :: [a] -> [a] -> [a]
+ Hasklepias.Reexports: (==) :: Eq a => a -> a -> Bool
+ Hasklepias.Reexports: Left :: a -> Either a b
+ Hasklepias.Reexports: Right :: b -> Either a b
+ Hasklepias.Reexports: any :: Foldable t => (a -> Bool) -> t a -> Bool
+ Hasklepias.Reexports: class Eq a
+ Hasklepias.Reexports: class Functor f => Filterable (f :: Type -> Type)
+ Hasklepias.Reexports: data Either a b
+ Hasklepias.Reexports: infixr 5 ++
+ Hasklepias.Types.Feature: FeatureData :: Either MissingReason d -> FeatureData d
+ Hasklepias.Types.Feature: FeatureSpec :: Text -> b -> FeatureDefinition f e a d -> FeatureSpec b f e a d
+ Hasklepias.Types.Feature: [getAttr] :: Feature b d -> b
+ Hasklepias.Types.Feature: [getData] :: Feature b d -> FeatureData d
+ Hasklepias.Types.Feature: [getDefn] :: FeatureSpec b f e a d -> FeatureDefinition f e a d
+ Hasklepias.Types.Feature: [getFeatureData] :: FeatureData d -> Either MissingReason d
+ Hasklepias.Types.Feature: [getName] :: Feature b d -> Text
+ Hasklepias.Types.Feature: [getSpecAttr] :: FeatureSpec b f e a d -> b
+ Hasklepias.Types.Feature: [getSpecName] :: FeatureSpec b f e a d -> Text
+ Hasklepias.Types.Feature: data (Show b) => Feature b d
+ Hasklepias.Types.Feature: data (Show b) => FeatureSpec b f e a d
+ Hasklepias.Types.Feature: evalEFFeature :: Show b => FeatureSpec b * * a d -> Events a -> Feature b d
+ Hasklepias.Types.Feature: evalFEFFeature :: Show b => FeatureSpec b * e a d -> Feature b e -> Events a -> Feature b d
+ Hasklepias.Types.Feature: evalFFFFeature :: Show b => FeatureSpec b f e * d -> Feature b f -> Feature b e -> Feature b d
+ Hasklepias.Types.Feature: instance GHC.Base.Functor Hasklepias.Types.Feature.FeatureData
+ Hasklepias.Types.Feature: instance GHC.Classes.Eq d => GHC.Classes.Eq (Hasklepias.Types.Feature.FeatureData d)
+ Hasklepias.Types.Feature: instance GHC.Generics.Generic (Hasklepias.Types.Feature.FeatureData d)
+ Hasklepias.Types.Feature: instance GHC.Show.Show d => GHC.Show.Show (Hasklepias.Types.Feature.FeatureData d)
+ Hasklepias.Types.Feature: newtype FeatureData d
+ Hasklepias.Types.Feature.Aeson: instance (GHC.Show.Show b, Data.Aeson.Types.ToJSON.ToJSON b, Data.Aeson.Types.ToJSON.ToJSON d) => Data.Aeson.Types.ToJSON.ToJSON (Hasklepias.Types.Feature.Feature b d)
+ Hasklepias.Types.Feature.Aeson: instance Data.Aeson.Types.ToJSON.ToJSON d => Data.Aeson.Types.ToJSON.ToJSON (Hasklepias.Types.Feature.FeatureData d)
- Hasklepias.Reexports: filter :: (a -> Bool) -> [a] -> [a]
+ Hasklepias.Reexports: filter :: Filterable f => (a -> Bool) -> f a -> f a
- Hasklepias.Types.Feature: EF :: (Events a -> Feature d) -> FeatureDefinition f e a d
+ Hasklepias.Types.Feature: EF :: (Events a -> FeatureData d) -> FeatureDefinition f e a d
- Hasklepias.Types.Feature: FEF :: (Feature e -> Events a -> Feature d) -> FeatureDefinition f e a d
+ Hasklepias.Types.Feature: FEF :: (FeatureData e -> Events a -> FeatureData d) -> FeatureDefinition f e a d
- Hasklepias.Types.Feature: FFF :: (Feature f -> Feature e -> Feature d) -> FeatureDefinition f e a d
+ Hasklepias.Types.Feature: FFF :: (FeatureData f -> FeatureData e -> FeatureData d) -> FeatureDefinition f e a d
- Hasklepias.Types.Feature: Feature :: Either MissingReason d -> Feature d
+ Hasklepias.Types.Feature: Feature :: Text -> b -> FeatureData d -> Feature b d
- Hasklepias.Types.Feature: Other :: String -> MissingReason
+ Hasklepias.Types.Feature: Other :: Text -> MissingReason
- Hasklepias.Types.Feature: applyEF :: FeatureDefinition * * a d -> Events a -> Feature d
+ Hasklepias.Types.Feature: applyEF :: FeatureDefinition * * a d -> Events a -> FeatureData d
- Hasklepias.Types.Feature: applyFEF :: FeatureDefinition * e a d -> Feature e -> Events a -> Feature d
+ Hasklepias.Types.Feature: applyFEF :: FeatureDefinition * e a d -> FeatureData e -> Events a -> FeatureData d
- Hasklepias.Types.Feature: applyFFF :: FeatureDefinition f e * d -> Feature f -> Feature e -> Feature d
+ Hasklepias.Types.Feature: applyFFF :: FeatureDefinition f e * d -> FeatureData f -> FeatureData e -> FeatureData d
- Hasklepias.Types.Feature: defineFEF2 :: Intervallic Interval a => MissingReason -> (e -> Events a -> Feature d) -> FeatureDefinition * e a d
+ Hasklepias.Types.Feature: defineFEF2 :: Intervallic Interval a => MissingReason -> (e -> Events a -> FeatureData d) -> FeatureDefinition * e a d
- Hasklepias.Types.Feature: featureL :: MissingReason -> Feature d
+ Hasklepias.Types.Feature: featureL :: MissingReason -> FeatureData d
- Hasklepias.Types.Feature: featureR :: d -> Feature d
+ Hasklepias.Types.Feature: featureR :: d -> FeatureData d
Files
- ChangeLog.md +8/−1
- README.md +1/−1
- examples/ExampleFeatures1.hs +13/−15
- examples/ExampleFeatures2.hs +1/−3
- examples/ExampleFeatures3.hs +1/−3
- hasklepias.cabal +2/−1
- src/Hasklepias/Reexports.hs +14/−3
- src/Hasklepias/Types/Context.hs +3/−3
- src/Hasklepias/Types/Feature.hs +74/−25
- src/Hasklepias/Types/Feature/Aeson.hs +14/−9
- test/Hasklepias/Types/Feature/AesonSpec.hs +1/−1
ChangeLog.md view
@@ -1,5 +1,12 @@ # Changelog for hasklepias +## 0.5.0++* Changes what was the `Feature` type into `FeatureData`. The `Feature` type becomes a container for `FeatureData` with a name and attributes.+* Adds the `FeatureSpec` type which contains `FeatureDefinition`s plus a name and attributes. The name and attributes are mapped directly into the resulting `Feature` when a `FeatureSpec` is evaluated, while the `FeatureDefinition` is evaluated into `FeatureData`. The `evalEFFeature`, `evalFEFFeature`, and `evalFFFFeature` are provided for evaluating a `FeatureSpec` according the corresponding `FeatureDefinition`.+* Adds additional functions to reexports.+* Adds `witherable` dependency to use a more general `filter` function.+ ## 0.4.4 * Adds the `FFF` option to `FeatureDefinition` to define `(Feature f -> Feature e -> Feature d)` along with corresponding `defineFFF` and `applyFFF`.@@ -14,7 +21,7 @@ ## 0.4.2 -* Updates `interval-algebra` to 0.8.0+* Updates `interval-algebra` to 0.8.0. ## 0.4.1
README.md view
@@ -20,7 +20,7 @@ At this time, `hasklepias` can be used for experimenting with `Feature` definitions. A `Feature d` is currently a wrapper of an [`Either`](https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Either.html) type: ```haskell-type Feature d = Feature { getFeature :: Either MissingReason d }+type Feature d = Feature { getFeatureData :: Either MissingReason d } ``` The `Either` type means there are two possibilities for the type of a `Feature`. The `Left` can be a `MissingReason`, which is a sum type enumerating the reasons that the data is missing:
examples/ExampleFeatures1.hs view
@@ -7,8 +7,6 @@ -} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE NoImplicitPrelude #-}@@ -35,22 +33,22 @@ {- The baseline interval is the interval (b - 60, b), where b is the begin of index. Here, baseline is defined as function that takes a filtration function-as an argument, so that the baseline feature can be used to filter events+as an argument, so that the baseline FeatureData can be used to filter events based on different predicate functions. -} baseline :: (Intervallic Interval a, IntervalSizeable a b) =>- Feature (Interval a) -- ^ pass the result of index to get a baseline filter- -> Feature (Interval a)+ FeatureData (Interval a) -- ^ pass the result of index to get a baseline filter+ -> FeatureData (Interval a) baseline = fmap (enderval 60 . begin) bline :: (Intervallic Interval a, IntervalSizeable a b) => Events a- -> Feature (Interval a)+ -> FeatureData (Interval a) bline = baseline . applyEF indexDef flwup :: (Intervallic Interval a, IntervalSizeable a b) => Events a- -> Feature (Interval a)+ -> FeatureData (Interval a) flwup = fmap (beginerval 30 . begin) . applyEF indexDef {-@@ -154,14 +152,14 @@ getUnitFeatures :: Events Int- -> (Feature (Interval Int)- , Feature Bool- , Feature (Bool, Maybe (Interval Int))- , Feature (Bool, Maybe (Interval Int))- , Feature Bool- , Feature (Maybe Int)- , Feature (Int, Maybe Int)- , Feature (Maybe (Int, Int))+ -> (FeatureData (Interval Int)+ , FeatureData Bool+ , FeatureData (Bool, Maybe (Interval Int))+ , FeatureData (Bool, Maybe (Interval Int))+ , FeatureData Bool+ , FeatureData (Maybe Int)+ , FeatureData (Int, Maybe Int)+ , FeatureData (Maybe (Int, Int)) ) getUnitFeatures x = ( applyEF indexDef x
examples/ExampleFeatures2.hs view
@@ -7,8 +7,6 @@ -} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE NoImplicitPrelude #-}@@ -24,7 +22,7 @@ , Intervallic Interval a , IntervalSizeable a b) => Events a- -> Feature [b]+ -> FeatureData [b] durationOfHospitalizedAntibiotics es | null y = featureL $ Other "no cases" | otherwise = featureR $ durations y
examples/ExampleFeatures3.hs view
@@ -7,8 +7,6 @@ -} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE NoImplicitPrelude #-}@@ -43,7 +41,7 @@ ) -flwup :: Feature (Interval Int)+flwup :: FeatureData (Interval Int) flwup = featureR $ beginerval 50 0 exampleFeatures3Spec :: Spec
hasklepias.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: hasklepias-version: 0.4.4+version: 0.5.0 description: Please see the README on GitHub at <https://github.com/novisci/asclepias#readme> homepage: https://github.com/novisci/asclepias/#readme bug-reports: https://github.com/novisci/asclepias/issues@@ -52,6 +52,7 @@ , safe >= 0.3 , vector >=0.12 , QuickCheck+ , witherable >= 0.4 default-language: Haskell2010 test-suite hasklepias-test
src/Hasklepias/Reexports.hs view
@@ -16,17 +16,20 @@ , module Control.Monad , module Control.Applicative , module Data.Bool- , module Data.Time.Calendar + , module Data.Either+ , module Data.Eq , module Data.Int , module Data.Maybe , module Data.Function , module Data.Functor , module Data.List , module Data.Ord+ , module Data.Time.Calendar , module Data.Text , module Data.Tuple , module Safe , module Flow+ , module Witherable ) where import safe GHC.Num ( Integer )@@ -36,11 +39,18 @@ , (&&), not, (||) , bool , otherwise )+import safe Data.Either ( Either(..))+import safe Data.Eq ( Eq, (==)) import safe Data.Function ( (.), ($), const, id ) import safe Data.Functor ( fmap ) import safe Data.Int ( Int )-import safe Data.List ( all, map, filter, length, null- , zipWith )+import safe Data.List ( all+ , any+ , map+ , length+ , null+ , zipWith+ , (++) ) import safe Data.Maybe ( Maybe(..), maybe, isJust,@@ -58,5 +68,6 @@ , diffDays ) import safe Data.Text ( pack, Text ) import safe Data.Tuple ( fst, snd, uncurry, curry )+import safe Witherable ( Filterable(filter) ) import safe Flow ( (!>), (.>), (<!), (<.), (<|), (|>) ) import Safe ( headMay, lastMay )
src/Hasklepias/Types/Context.hs view
@@ -29,14 +29,14 @@ import GHC.Show ( Show(show) ) import Data.Bool ( Bool ) import Data.Eq ( Eq )-import Data.Function ((.), ($))+import Data.Function ( (.), ($) ) import Data.List ( all, any, map ) import Data.Maybe ( Maybe(Nothing) ) import Data.Monoid ( (<>), Monoid(mempty) ) import Data.Ord ( Ord ) import Data.Semigroup ( Semigroup((<>)) )-import Data.Text (Text)-import Data.Set (Set+import Data.Text ( Text )+import Data.Set ( Set , fromList, union, empty, map, toList, member) -- | A @Context@ consists of three parts: @concepts@, @facts@, and @source@.
src/Hasklepias/Types/Feature.hs view
@@ -15,7 +15,9 @@ module Hasklepias.Types.Feature( -- * Types- Feature(..)+ FeatureSpec(..)+ , Feature(..)+ , FeatureData(..) , MissingReason(..) , FeatureDefinition(..) , defineEF@@ -27,52 +29,79 @@ , applyFFF , featureR , featureL-+ , evalEFFeature+ , evalFEFFeature+ , evalFFFFeature ) where import GHC.Read ( Read ) import GHC.Show ( Show )-import GHC.Generics ( Generic )+import GHC.Generics ( Generic, D ) import Data.Either ( Either(..) ) import Data.Eq ( Eq ) import Data.Functor ( Functor(fmap) ) import Data.Function ( ($), (.) ) import Data.Maybe ( Maybe(..) )-import Data.String ( String )+import Data.Text ( Text ) import Hasklepias.Types.Event ( Events ) import IntervalAlgebra ( Interval, Intervallic )+-- import safe Test.QuickCheck ( Property ) -{- | A 'Feature' is a @'Either' 'MissingReason' d@, where @d@ can be any type +{- | A 'FeatureSpec' contains all the information needed to derive a 'Feature':+ * its name+ * its attributes+ * the function needed to derive a feature (i.e. the 'FeatureDefinition')+-}+data (Show b) => FeatureSpec b f e a d = FeatureSpec {+ getSpecName :: Text+ , getSpecAttr :: b+ , getDefn :: FeatureDefinition f e a d+ -- To add in future: an optional list of properties to check+ -- , getProp :: Maybe [Feature d -> Events a -> Property] + }++{- | A 'Feature' contains the following:+ * a name+ * its attributes+ * 'FeatureData'+-}+data (Show b) => Feature b d = Feature {+ getName :: Text+ , getAttr :: b+ , getData :: FeatureData d + }++{- | 'FeatureData' is @'Either' 'MissingReason' d@, where @d@ can be any type of data derivable from 'Hasklepias.Event.Events'. -}-newtype Feature d = Feature { getFeature :: Either MissingReason d }+newtype FeatureData d = FeatureData { getFeatureData :: Either MissingReason d } deriving (Generic, Show, Eq) -instance Functor Feature where- fmap f (Feature x) = Feature (fmap f x)+instance Functor FeatureData where+ fmap f (FeatureData x) = FeatureData (fmap f x) -- | Create the 'Right' side of a 'Feature'.-featureR :: d -> Feature d-featureR = Feature . Right+featureR :: d -> FeatureData d+featureR = FeatureData . Right -- | Create the 'Left' side of a 'Feature'.-featureL :: MissingReason -> Feature d-featureL = Feature . Left+featureL :: MissingReason -> FeatureData d+featureL = FeatureData . Left -- | A 'Feature' may be missing for any number of reasons. data MissingReason = InsufficientData | Excluded- | Other String+ | Other Text | Unknown deriving (Eq, Read, Show, Generic) --- | A type to hold common feature definitions; i.e. functions that return +-- | A type to hold common FeatureData definitions; i.e. functions that return -- features. data FeatureDefinition f e a d =- EF (Events a -> Feature d)- | FEF (Feature e -> Events a -> Feature d)- | FFF (Feature f -> Feature e -> Feature d)+ EF (Events a -> FeatureData d)+ | FEF (FeatureData e -> Events a -> FeatureData d)+ | FFF (FeatureData f -> FeatureData e -> FeatureData d) -- | Define an 'EF' FeatureDefinition defineEF :: (Intervallic Interval a) =>@@ -81,7 +110,7 @@ -> (Events a -> Maybe c) -- ^ A function that maps events to an some intermediary Maybe type. -- In the case that this function returns 'Nothing', you get a - -- @Left@ feature with the provided @MissingReason@. Otherwise, + -- @Left@ FeatureData with the provided @MissingReason@. Otherwise, -- the 'Just' result is passed to the next function for final -- transformation to the desired @Feature@ type. -> (c -> d) @@ -95,7 +124,7 @@ ) -- | Extract an 'EF' FeatureDefinition.-applyEF :: FeatureDefinition * * a d -> Events a -> Feature d+applyEF :: FeatureDefinition * * a d -> Events a -> FeatureData d applyEF (EF f) = f -- | TODO@@ -106,7 +135,7 @@ -- ^ A function that tranforms the data of a 'Right' input 'Feature' -- and a collection of events into the desired type. -> FeatureDefinition * e a d-defineFEF r g = FEF (\(Feature feat) es ->+defineFEF r g = FEF (\(FeatureData feat) es -> case feat of (Left _) -> featureL r (Right x) -> featureR (g x es)@@ -116,18 +145,18 @@ defineFEF2 :: (Intervallic Interval a) => MissingReason -- ^ The reason if the input 'Feature' is a 'Left'.- -> (e -> Events a -> Feature d)+ -> (e -> Events a -> FeatureData d) -- ^ A function that tranforms the data of a 'Right' input 'Feature' -- and a collection of events into the desired type. -> FeatureDefinition * e a d-defineFEF2 r g = FEF (\(Feature feat) es ->+defineFEF2 r g = FEF (\(FeatureData feat) es -> case feat of (Left _) -> featureL r (Right x) -> g x es ) -- | Extract a 'FEF' FeatureDefinition-applyFEF :: FeatureDefinition * e a d -> Feature e -> Events a -> Feature d+applyFEF :: FeatureDefinition * e a d -> FeatureData e -> Events a -> FeatureData d applyFEF (FEF f) = f -- | TODO@@ -136,7 +165,7 @@ -> MissingReason -> (f -> e -> d) -> FeatureDefinition f e * d-defineFFF r1 r2 g = FFF (\(Feature feat1) (Feature feat2) ->+defineFFF r1 r2 g = FFF (\(FeatureData feat1) (FeatureData feat2) -> case ( feat1, feat2 ) of ( Left _ , Left _ ) -> featureL r1 ( Left _ , _ ) -> featureL r1@@ -145,5 +174,25 @@ ) -- | Extract a 'FFF' FeatureDefinition-applyFFF :: FeatureDefinition f e * d -> Feature f -> Feature e -> Feature d+applyFFF :: FeatureDefinition f e * d -> FeatureData f -> FeatureData e -> FeatureData d applyFFF (FFF f) = f++-- | TODO+makeFeatureSpec :: Show b => Text -> b -> FeatureDefinition f e a d -> + FeatureSpec b f e a d+makeFeatureSpec = FeatureSpec++-- | TODO+evalEFFeature :: Show b => FeatureSpec b * * a d -> Events a -> Feature b d +evalEFFeature (FeatureSpec n atr def) es = + Feature n atr (applyEF def es)++-- | TODO +evalFEFFeature :: Show b => FeatureSpec b * e a d -> Feature b e -> Events a -> Feature b d +evalFEFFeature (FeatureSpec n atr def) feat es =+ Feature n atr (applyFEF def (getData feat) es)++-- | TODO+evalFFFFeature :: Show b => FeatureSpec b f e * d -> Feature b f -> Feature b e -> Feature b d +evalFFFFeature (FeatureSpec n atr def) feat1 feat2 =+ Feature n atr (applyFFF def (getData feat1) (getData feat2))
src/Hasklepias/Types/Feature/Aeson.hs view
@@ -11,18 +11,23 @@ module Hasklepias.Types.Feature.Aeson( ) where -import IntervalAlgebra-import GHC.Generics-import Hasklepias.Types.Feature ( MissingReason, Feature(..) )-import Data.Aeson--- ( ToJSON, toJSON )+import IntervalAlgebra ( Interval, Intervallic(end, begin) )+import Hasklepias.Types.Feature ( Feature(..)+ , MissingReason+ , FeatureData(..) )+import Data.Aeson ( object, KeyValue((.=)), ToJSON(toJSON) ) instance (ToJSON a, Ord a, Show a)=> ToJSON (Interval a) where- toJSON x = - object ["begin" .= begin x, "end" .= end x]+ toJSON x = object ["begin" .= begin x, "end" .= end x]+ instance ToJSON MissingReason -instance (ToJSON d)=> ToJSON (Feature d) where- toJSON x = case getFeature x of ++instance (ToJSON d)=> ToJSON (FeatureData d) where+ toJSON x = case getFeatureData x of (Left l) -> toJSON l (Right r) -> toJSON r +instance (Show b, ToJSON b, ToJSON d) => ToJSON (Feature b d) where+ toJSON x = object [ "name" .= getName x+ , "attrs" .= toJSON (getAttr x)+ , "data" .= toJSON (getData x) ]
test/Hasklepias/Types/Feature/AesonSpec.hs view
@@ -19,7 +19,7 @@ index:: (Intervallic Interval a) => Events a- -> Feature (Interval a)+ -> FeatureData (Interval a) index es = case firstConceptOccurrence ["enrollment"] es of Nothing -> featureL (Other "No Enrollment")