packages feed

fraxl-0.2.0.0: tests/ExampleDataSource.hs

{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE StandaloneDeriving         #-}

module ExampleDataSource
  (
    -- * requests for this data source
    Id(..)
  , ExampleReq(..)
  , fetchExample
  , countAardvarks
  , listWombats
  )
where

import           Control.Monad.Fraxl

-- Here is an example minimal data source.  Our data source will have
-- two requests:
--
--   countAardvarks :: String -> Haxl Int
--   listWombats    :: Id     -> Haxl [Id]
--
-- First, the data source defines a request type, with one constructor
-- for each request:

newtype Id = Id Int
  deriving (Eq, Ord, Enum, Num, Integral, Real)

instance Show Id where
  show (Id i) = show i

data ExampleReq a where
  CountAardvarks :: String -> ExampleReq Int
  ListWombats    :: Id     -> ExampleReq [Id]

-- The request type (ExampleReq) is parameterized by the result type of
-- each request.  Each request might have a different result, so we use a
-- GADT - a data type in which each constructor may have different type
-- parameters. Here CountAardvarks is a request that takes a String
-- argument and its result is Int, whereas ListWombats takes an Id
-- argument and returns a [Id].

deriving instance Show (ExampleReq a)

instance GEq ExampleReq where
  CountAardvarks _ `geq` CountAardvarks _ = Just Refl
  ListWombats _ `geq` ListWombats _ = Just Refl
  _ `geq` _ = Nothing

instance GCompare ExampleReq where
  CountAardvarks a `gcompare` CountAardvarks b = case a `compare` b of
    EQ -> GEQ
    LT -> GLT
    GT -> GGT
  ListWombats a `gcompare` ListWombats b = case a `compare` b of
    EQ -> GEQ
    LT -> GLT
    GT -> GGT
  CountAardvarks _ `gcompare` ListWombats _ = GLT
  ListWombats _ `gcompare` CountAardvarks _ = GGT

-- We need to define an instance of DataSource:

fetchExample :: Monad m => Fetch ExampleReq m a
fetchExample ANil = return ANil
fetchExample (ACons (CountAardvarks str) rs) =
  ACons <$> return (return (length (filter (== 'a') str))) <*> fetchExample rs
fetchExample (ACons (ListWombats a) rs) =
  ACons <$> return (return (take (fromIntegral a) [1 ..])) <*> fetchExample rs

countAardvarks :: MonadFraxl ExampleReq m => String -> m Int
countAardvarks str = dataFetch (CountAardvarks str)

listWombats :: MonadFraxl ExampleReq m => Id -> m [Id]
listWombats a = dataFetch (ListWombats a)