shady-gen-0.5.1: src/Shady/Misc.hs
{-# LANGUAGE TypeOperators, FlexibleContexts, TypeFamilies
, UndecidableInstances #-}
-- {-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
{-# OPTIONS_GHC -Wall #-}
----------------------------------------------------------------------
-- |
-- Module : Shady.Misc
-- Copyright : (c) Conal Elliott 2009
-- License : AGPLv3
--
-- Maintainer : conal@conal.net
-- Stability : experimental
--
-- Misc useful definitions
----------------------------------------------------------------------
module Shady.Misc
( -- argument, result, (~>),
FMod(..), Frac(..), fmodRF, fracRF, fmodViaFrac, fracViaFmod
, clamp, clampB, smoothStep
, Unop,Binop
, padTo
, flip1, flip2, flip3, flip4
, Sink, Action, (>+>), forget
, R
-- * Find another home
, EyePos
) where
import Control.Applicative ((<$))
-- From TypeCompose package
import Control.Compose (result)
import Control.Instances ()
import Data.Maclaurin ((:>)(..)) -- For Frac instance
import Data.Boolean
type R = Float
-- | Clamp to a given range
clamp :: Ord a => (a,a) -> a -> a
clamp (lo,hi) = max lo . min hi
-- | Variation on 'clamp', using 'OrdB' instead of 'Ord'
clampB :: (IfB bool a, OrdB bool a) => (a,a) -> a -> a
clampB (lo,hi) = maxB lo . minB hi
-- | Smooth, clamped transition
smoothStep :: (Ord a, Num a) => (a,a) -> a -> a
smoothStep loHi val = t*t*(3-2*t) where t = clamp loHi val
-- | Unary transformation (endomorphism)
type Unop a = a -> a
-- | Binary transformation
type Binop a = a -> a -> a
-- | Pad a string to the given length, adding spaces on the right as needed.
padTo :: Int -> String -> String
padTo n str = str ++ replicate (n - length str) ' '
-- | Move first argument to first place (for style uniformity)
flip1 :: (a -> b) -> (a -> b)
flip1 = id
-- | Move second argument to first place ('flip' synonym for style uniformity)
flip2 :: (a -> b -> c) -> (b -> a -> c)
flip2 = flip
-- | Move third argument to first place
flip3 :: (a -> b -> c -> d) -> (c -> a -> b -> d)
flip3 = flip . result flip
-- | Move fourth argument to first place
flip4 :: (a -> b -> c -> d -> e) -> (d -> a -> b -> c -> e)
flip4 = flip . result flip3
{--------------------------------------------------------------------
frac & fmod
--------------------------------------------------------------------}
-- | Take fractional component(s). Always non-negative. You can use
-- 'fracRF' for 'RealFrac' types and 'fracViaFmod' for 'Fmod' types.
class Frac a where frac :: a -> a
-- | Real-valued modulo. You can use 'fmodRF' for 'RealFrac' types and
-- 'fmodViaFrac' for 'Frac' types.
class FMod a where fmod :: a -> a -> a
-- | Fractional component. Useful for defining 'frac' on 'RealFrac' types.
fracRF :: RealFrac a => a -> a
fracRF x = x - fromIntegral (floor x :: Int)
-- | Fractional modulo. Useful for defining 'fmod' on 'RealFrac' types.
fmodRF :: RealFrac a => a -> a -> a
x `fmodRF` y = x - y * fromIntegral (floor (x/y) :: Int)
-- | Handy defining 'frac' on a 'FMod' type.
fracViaFmod :: (Num a, FMod a) => a -> a
fracViaFmod = (`fmod` 1)
-- | Handy defining 'fmod' on a 'Frac' type.
fmodViaFrac :: (Fractional a, Frac a) => a -> a -> a
x `fmodViaFrac` y = frac (x/y) * y
instance FMod Float where fmod = fmodRF
instance Frac Float where frac = fracRF
-- 'frac' of a derivative tower is 'frac' of the value and unchanged
-- derivatives. Not quite right, since 'frac' introduces discontinuities,
-- so all-sided derivatives don't really exist at those points.
instance Frac s => Frac (u :> s) where
frac (D s l) = D (frac s) l
{--------------------------------------------------------------------
Information sinks
--------------------------------------------------------------------}
-- | Synonym for @IO ()@. Obviates some parentheses.
type Action = IO ()
-- | Sink of information
type Sink a = a -> Action
infixr 1 >+>
-- | Combine sinks
(>+>) :: Sink a -> Sink b -> Sink (a,b)
(sa >+> sb) (a,b) = sa a >> sb b
-- | Discard a functor value.
forget :: Functor f => f a -> f ()
forget = (() <$)
-- forget = fmap (const ())
{--------------------------------------------------------------------
Find another home
--------------------------------------------------------------------}
type EyePos = (R,R,R)