{-# LANGUAGE Unsafe, CPP #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Metrology.Unsafe
-- Copyright   :  (C) 2013 Richard Eisenberg
-- License     :  BSD-style (see LICENSE)
-- Maintainer  :  Richard Eisenberg (rae@cs.brynmawr.edu)
-- Stability   :  experimental
-- Portability :  non-portable
--
-- This module exports the constructor of the 'Qu' type. This allows you
-- to write code that takes creates and reads quantities at will,
-- which may lead to dimension unsafety. Use at your peril.
--
-- This module also exports 'UnsafeQu', which is a simple wrapper around
-- 'Qu' that has 'Functor', etc., instances. The reason 'Qu' itself doesn't
-- have a 'Functor' instance is that it would be unit-unsafe, allowing you,
-- say, to add 1 to a quantity.... but 1 what? That's the problem. However,
-- a 'Functor' instance is likely useful, hence 'UnsafeQu'.
-----------------------------------------------------------------------------

module Data.Metrology.Unsafe (
  -- * The 'Qu' type
  Qu(..),

  -- * 'UnsafeQu'
  UnsafeQu(..)
  ) where

import Data.Metrology.Qu

#if __GLASGOW_HASKELL__ < 709
import Control.Applicative
import Data.Foldable
import Data.Traversable
#endif

-- | A basic wrapper around 'Qu' that has more instances.
newtype UnsafeQu d l n = UnsafeQu { UnsafeQu d l n -> Qu d l n
qu :: Qu d l n }

instance Functor (UnsafeQu d l) where
  fmap :: (a -> b) -> UnsafeQu d l a -> UnsafeQu d l b
fmap a -> b
f (UnsafeQu (Qu a
x)) = Qu d l b -> UnsafeQu d l b
forall (d :: [Factor *]) (l :: LCSU *) n.
Qu d l n -> UnsafeQu d l n
UnsafeQu (b -> Qu d l b
forall (a :: [Factor *]) (lcsu :: LCSU *) n. n -> Qu a lcsu n
Qu (a -> b
f a
x))

instance Applicative (UnsafeQu d l) where
  pure :: a -> UnsafeQu d l a
pure a
x = Qu d l a -> UnsafeQu d l a
forall (d :: [Factor *]) (l :: LCSU *) n.
Qu d l n -> UnsafeQu d l n
UnsafeQu (a -> Qu d l a
forall (a :: [Factor *]) (lcsu :: LCSU *) n. n -> Qu a lcsu n
Qu a
x)
  UnsafeQu (Qu a -> b
f) <*> :: UnsafeQu d l (a -> b) -> UnsafeQu d l a -> UnsafeQu d l b
<*> UnsafeQu (Qu a
x) = Qu d l b -> UnsafeQu d l b
forall (d :: [Factor *]) (l :: LCSU *) n.
Qu d l n -> UnsafeQu d l n
UnsafeQu (b -> Qu d l b
forall (a :: [Factor *]) (lcsu :: LCSU *) n. n -> Qu a lcsu n
Qu (a -> b
f a
x))

instance Foldable (UnsafeQu d l) where
  foldMap :: (a -> m) -> UnsafeQu d l a -> m
foldMap a -> m
f (UnsafeQu (Qu a
x)) = a -> m
f a
x

instance Traversable (UnsafeQu d l) where
  traverse :: (a -> f b) -> UnsafeQu d l a -> f (UnsafeQu d l b)
traverse a -> f b
f (UnsafeQu (Qu a
x)) = Qu d l b -> UnsafeQu d l b
forall (d :: [Factor *]) (l :: LCSU *) n.
Qu d l n -> UnsafeQu d l n
UnsafeQu (Qu d l b -> UnsafeQu d l b)
-> (b -> Qu d l b) -> b -> UnsafeQu d l b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Qu d l b
forall (a :: [Factor *]) (lcsu :: LCSU *) n. n -> Qu a lcsu n
Qu (b -> UnsafeQu d l b) -> f b -> f (UnsafeQu d l b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
x