|
10 | 10 | {-# LANGUAGE UndecidableInstances #-} |
11 | 11 | {-# LANGUAGE MultiParamTypeClasses #-} |
12 | 12 | {-# LANGUAGE BangPatterns #-} |
| 13 | +{-# LANGUAGE TemplateHaskell #-} |
13 | 14 | module DataFrame.Functions where |
14 | 15 |
|
15 | | -import DataFrame.Internal.Column (Columnable) |
| 16 | +import DataFrame.Internal.Column |
| 17 | +import DataFrame.Internal.DataFrame (DataFrame(..), unsafeGetColumn) |
16 | 18 | import DataFrame.Internal.Expression (Expr(..), UExpr(..)) |
17 | 19 |
|
| 20 | +import Control.Monad |
| 21 | +import Data.Function |
| 22 | +import qualified Data.List as L |
| 23 | +import qualified Data.Map as M |
18 | 24 | import qualified Data.Text as T |
19 | 25 | import qualified Data.Vector.Generic as VG |
20 | 26 | import qualified Data.Vector.Unboxed as VU |
| 27 | +import qualified Data.Vector as VB |
| 28 | +import Language.Haskell.TH |
| 29 | +import qualified Language.Haskell.TH.Syntax as TH |
21 | 30 |
|
22 | 31 | col :: Columnable a => T.Text -> Expr a |
23 | 32 | col = Col |
@@ -68,3 +77,31 @@ mean (Col name) = let |
68 | 77 | (!total, !n) = VG.foldl' (\(!total, !n) v -> (total + v, n + 1)) (0 :: Double, 0 :: Int) samp |
69 | 78 | in total / fromIntegral n |
70 | 79 | in NumericAggregate name "mean" mean' |
| 80 | + |
| 81 | +-- TODO: Enumerate universe of primitives. |
| 82 | +-- Maybe this should go in a separate module where people can add their |
| 83 | +-- universe of types. |
| 84 | +-- Or maybe make it easier to insert your on types here. |
| 85 | +typeFromString :: String -> Q Type |
| 86 | +typeFromString s = case s of |
| 87 | + "Int" -> [t| Int |] |
| 88 | + "Double" -> [t| Double |] |
| 89 | + "Bool" -> [t| Bool |] |
| 90 | + "Text" -> [t| T.Text |] |
| 91 | + "Maybe Int" -> [t| Maybe Int |] |
| 92 | + "Maybe Double" -> [t| Maybe Double |] |
| 93 | + "Maybe Bool" -> [t| Maybe Bool |] |
| 94 | + "Maybe Text" -> [t| Maybe T.Text |] |
| 95 | + _ -> fail $ "Unsupported type: " ++ s |
| 96 | + |
| 97 | +declareColumns :: DataFrame -> DecsQ |
| 98 | +declareColumns df = let |
| 99 | + names = (map fst . L.sortBy (compare `on` snd). M.toList . columnIndices) df |
| 100 | + types = map (columnTypeString . (`unsafeGetColumn` df)) names |
| 101 | + specs = zip names types |
| 102 | + in fmap concat $ forM specs $ \(nm, tyStr) -> do |
| 103 | + ty <- typeFromString tyStr |
| 104 | + let n = mkName (T.unpack nm) |
| 105 | + sig <- sigD n [t| Expr $(pure ty) |] |
| 106 | + val <- valD (varP n) (normalB [| col $(TH.lift nm) |]) [] |
| 107 | + pure [sig, val] |
0 commit comments