Skip to content

Commit

Permalink
Coerce all the things
Browse files Browse the repository at this point in the history
Use coercions to imitate GND for classes GND doesn't work with.
Should we do this? I'm not sure.
  • Loading branch information
treeowl committed Dec 9, 2016
1 parent 14b5395 commit 20743de
Showing 1 changed file with 40 additions and 7 deletions.
47 changes: 40 additions & 7 deletions src/Linear/Affine.hs
Expand Up @@ -12,7 +12,7 @@
{-# LANGUAGE DeriveGeneric #-}
#endif
{-# LANGUAGE DeriveDataTypeable #-}
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < 708
#if defined(__GLASGOW_HASKELL__)
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
#endif
Expand All @@ -33,6 +33,9 @@ import Control.Monad (liftM)
import Control.Lens
import Data.Binary as Binary
import Data.Bytes.Serial
#if __GLASGOW_HASKELL__ >= 708
import Data.Coerce
#endif
import Data.Complex (Complex)
import Data.Data
import Data.Distributive
Expand Down Expand Up @@ -190,17 +193,47 @@ instance Wrapped (Point f a) where
_Wrapped' = _Point
{-# INLINE _Wrapped' #-}

#if __GLASGOW_HASKELL__ >= 708
-- These are stolen from Data.Profunctor.Unsafe
(.#) :: Coercible b a => (b -> c) -> (a -> b) -> a -> c
f .# _ = coerce f
{-# INLINE (.#) #-}

(#.) :: Coercible c b => (b -> c) -> (a -> b) -> a -> c
(#.) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
{-# INLINE (#.) #-}
#else
(.#), (#.) :: (b -> c) -> (a -> b) -> a -> c
(.#) = (.)
{-# INLINE (.#) #-}
(#.) = (.)
{-# INLINE (#.) #-}
#endif

unP :: Point f a -> f a
unP (P x) = x
{-# INLINE unP #-}

-- We can't use GND to derive 'Bind' because 'join' causes
-- role troubles. However, GHC 7.8 and above let us use
-- explicit coercions for (>>-).
instance Bind f => Bind (Point f) where
join (P m) = P $ join $ fmap (\(P m')->m') m
#if __GLASGOW_HASKELL__ >= 708
(>>-) = ((P .) . (. (unP .))) #. (>>-) .# unP
#else
P m >>- f = P $ m >>- unP . f
#endif
join (P m) = P $ m >>- \(P m') -> m'

instance Distributive f => Distributive (Point f) where
distribute = P . collect (\(P p) -> p)
collect = (P .) #. collect .# (unP .)

instance Representable f => Representable (Point f) where
type Rep (Point f) = Rep f
tabulate f = P (tabulate f)
tabulate = P #. tabulate
{-# INLINE tabulate #-}
index (P xs) = Rep.index xs
index = Rep.index .# unP
{-# INLINE index #-}

type instance Index (Point f a) = Index (f a)
Expand Down Expand Up @@ -238,11 +271,11 @@ instance R4 f => R4 (Point f) where

instance Additive f => Affine (Point f) where
type Diff (Point f) = f
P x .-. P y = x ^-^ y
(.-.) = (. unP) #. (^-^) .# unP
{-# INLINE (.-.) #-}
P x .+^ v = P (x ^+^ v)
(.+^) = (P .) #. (^+^) .# unP
{-# INLINE (.+^) #-}
P x .-^ v = P (x ^-^ v)
(.-^) = (P .) #. (^-^) .# unP
{-# INLINE (.-^) #-}

-- | Vector spaces have origins.
Expand Down

0 comments on commit 20743de

Please sign in to comment.