language-ninja-0.1.0: library/Language/Ninja/Mock/ReadFile.hs
-- -*- coding: utf-8; mode: haskell; -*-
-- File: library/Language/Ninja/Mock/ReadFile.hs
--
-- License:
-- Copyright 2017 Awake Security
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
-- |
-- Module : Language.Ninja.Mock.ReadFile
-- Copyright : Copyright 2017 Awake Security
-- License : Apache-2.0
-- Maintainer : opensource@awakesecurity.com
-- Stability : experimental
--
-- A typeclass exposing an interface that allows reading a file from a
-- filesystem (virtual or otherwise).
--
-- @since 0.1.0
module Language.Ninja.Mock.ReadFile
( MonadReadFile (..)
) where
import Prelude (IO, Monad)
import Control.Monad.Trans.Class (MonadTrans (lift))
import qualified Control.Lens as Lens
import Data.Text (Text)
import qualified Data.Text.IO as Text
import Language.Ninja.Misc.Path (Path, pathString)
import Flow ((.>))
--------------------------------------------------------------------------------
-- Remember: we have imported Prelude hiding 'readFile'.
-- | This typeclass allows you to write code that reads files from the
-- filesystem and then later run that code purely against a virtual filesystem
-- of some description.
--
-- @since 0.1.0
class (Monad m) => MonadReadFile m where
{-# MINIMAL readFile #-}
-- | Read the file located at the given path and decode it into 'Text'.
--
-- TODO: some notion of error handling should be encoded into the type
--
-- @since 0.1.0
readFile :: Path -> m Text
-- | The obvious instance for 'IO'.
--
-- @since 0.1.0
instance MonadReadFile IO where
readFile = Lens.view pathString .> Text.readFile
-- | A placeholder (undecidable) instance that allows this constraint to
-- propagate through monad transformers without needing to 'lift' manually.
--
-- @since 0.1.0
instance ( MonadTrans t, Monad (t m), MonadReadFile m
) => MonadReadFile (t m) where
readFile = readFile .> lift
--------------------------------------------------------------------------------