[Haskell-cafe] Mocking out external services

Francesco Ariis fa-ml at ariis.it
Sun May 19 10:25:26 UTC 2019


(literate Haskell follows)

Hello -cafe,
    I recently read "Three Layer Haskell Cake" [1] and decided to give
it a go. I am stuck on a simple problem and feel like I am missing
something easy.
One of the first examples is a mocking of an `IO UTCTime` function.

>
> {-# Language FlexibleInstances #-}
>
> data UTCTime = UTCTime Int
>
> class MonadTime m where
>    getCurrentTime :: m UTCTime
>
> instance MonadTime ((->) UTCTime) where
>     getCurrentTime = id
>
> -- instance IO omitted
>

Everything is clear. I decided to write another function, mocking
a stream-of-Char input.

>
> class MonadKeys m where
>     getKeys :: m [Char]
>
> instance MonadKeys ((->) [Char]) where
>     getKeys = id
>
> -- instance IO omitted
>

Again, fine. But now, if I want to write a function which combines the
two external services, like:

>
> someFun :: (MonadTime m, MonadKeys m) => m ()
> someFun = undefined
>

there is no non-IO instance satisfying the two constraints. I could of
course write a type

>
> data Env = Env UTCTime [Char]
>

and make it instance of MonadTime and MonadKeys, but then I am passing
non-relevant arguments to a mocked function like getCurrentTime, which
would only need UTCTime.

What am I doing incorrectly?
-F


[1] https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html




More information about the Haskell-Cafe mailing list