{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleInstances #-}
module Graphics.Rasterific.Types
(
Vector
, Point
, Line( .. )
, Bezier( .. )
, CubicBezier( .. )
, Primitive( .. )
, Primitivable( .. )
, Geometry( .. )
, Producer
, Container
, containerOfList
, listOfContainer
, containerOfFunction
, PathCommand( .. )
, Path( .. )
, Transformable( .. )
, PointFoldable( .. )
, Cap( .. )
, Join( .. )
, FillMethod( .. )
, SamplerRepeat( .. )
, DashPattern
, StrokeWidth
, EdgeSample( .. )
, pathToPrimitives
, firstTangeantOf
, lastTangeantOf
, firstPointOf
, lastPointOf
, resplit
, Proxy( Proxy )
) where
import Data.DList( DList, fromList )
import Control.Monad.Identity( runIdentity )
import Data.Foldable( foldl', toList )
import qualified Data.Foldable as F
import Graphics.Rasterific.Linear( V2( .. ), (^-^), nearZero )
import Graphics.Rasterific.Operators
import Foreign.Ptr( castPtr )
import Foreign.Storable( Storable( sizeOf
, alignment
, peek
, poke
, peekElemOff
, pokeElemOff ) )
type Vector = V2 Float
type StrokeWidth = Float
type DashPattern = [Float]
data Proxy p = Proxy
data Cap
= CapStraight Float
| CapRound
deriving (Cap -> Cap -> Bool
(Cap -> Cap -> Bool) -> (Cap -> Cap -> Bool) -> Eq Cap
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Cap -> Cap -> Bool
$c/= :: Cap -> Cap -> Bool
== :: Cap -> Cap -> Bool
$c== :: Cap -> Cap -> Bool
Eq, Int -> Cap -> ShowS
[Cap] -> ShowS
Cap -> String
(Int -> Cap -> ShowS)
-> (Cap -> String) -> ([Cap] -> ShowS) -> Show Cap
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Cap] -> ShowS
$cshowList :: [Cap] -> ShowS
show :: Cap -> String
$cshow :: Cap -> String
showsPrec :: Int -> Cap -> ShowS
$cshowsPrec :: Int -> Cap -> ShowS
Show)
data Join
= JoinRound
| JoinMiter Float
deriving (Join -> Join -> Bool
(Join -> Join -> Bool) -> (Join -> Join -> Bool) -> Eq Join
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Join -> Join -> Bool
$c/= :: Join -> Join -> Bool
== :: Join -> Join -> Bool
$c== :: Join -> Join -> Bool
Eq, Int -> Join -> ShowS
[Join] -> ShowS
Join -> String
(Int -> Join -> ShowS)
-> (Join -> String) -> ([Join] -> ShowS) -> Show Join
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Join] -> ShowS
$cshowList :: [Join] -> ShowS
show :: Join -> String
$cshow :: Join -> String
showsPrec :: Int -> Join -> ShowS
$cshowsPrec :: Int -> Join -> ShowS
Show)
data FillMethod
= FillWinding
| FillEvenOdd
deriving (FillMethod -> FillMethod -> Bool
(FillMethod -> FillMethod -> Bool)
-> (FillMethod -> FillMethod -> Bool) -> Eq FillMethod
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FillMethod -> FillMethod -> Bool
$c/= :: FillMethod -> FillMethod -> Bool
== :: FillMethod -> FillMethod -> Bool
$c== :: FillMethod -> FillMethod -> Bool
Eq, Int -> FillMethod
FillMethod -> Int
FillMethod -> [FillMethod]
FillMethod -> FillMethod
FillMethod -> FillMethod -> [FillMethod]
FillMethod -> FillMethod -> FillMethod -> [FillMethod]
(FillMethod -> FillMethod)
-> (FillMethod -> FillMethod)
-> (Int -> FillMethod)
-> (FillMethod -> Int)
-> (FillMethod -> [FillMethod])
-> (FillMethod -> FillMethod -> [FillMethod])
-> (FillMethod -> FillMethod -> [FillMethod])
-> (FillMethod -> FillMethod -> FillMethod -> [FillMethod])
-> Enum FillMethod
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: FillMethod -> FillMethod -> FillMethod -> [FillMethod]
$cenumFromThenTo :: FillMethod -> FillMethod -> FillMethod -> [FillMethod]
enumFromTo :: FillMethod -> FillMethod -> [FillMethod]
$cenumFromTo :: FillMethod -> FillMethod -> [FillMethod]
enumFromThen :: FillMethod -> FillMethod -> [FillMethod]
$cenumFromThen :: FillMethod -> FillMethod -> [FillMethod]
enumFrom :: FillMethod -> [FillMethod]
$cenumFrom :: FillMethod -> [FillMethod]
fromEnum :: FillMethod -> Int
$cfromEnum :: FillMethod -> Int
toEnum :: Int -> FillMethod
$ctoEnum :: Int -> FillMethod
pred :: FillMethod -> FillMethod
$cpred :: FillMethod -> FillMethod
succ :: FillMethod -> FillMethod
$csucc :: FillMethod -> FillMethod
Enum, Int -> FillMethod -> ShowS
[FillMethod] -> ShowS
FillMethod -> String
(Int -> FillMethod -> ShowS)
-> (FillMethod -> String)
-> ([FillMethod] -> ShowS)
-> Show FillMethod
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FillMethod] -> ShowS
$cshowList :: [FillMethod] -> ShowS
show :: FillMethod -> String
$cshow :: FillMethod -> String
showsPrec :: Int -> FillMethod -> ShowS
$cshowsPrec :: Int -> FillMethod -> ShowS
Show)
data SamplerRepeat
= SamplerPad
| SamplerRepeat
| SamplerReflect
deriving (SamplerRepeat -> SamplerRepeat -> Bool
(SamplerRepeat -> SamplerRepeat -> Bool)
-> (SamplerRepeat -> SamplerRepeat -> Bool) -> Eq SamplerRepeat
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SamplerRepeat -> SamplerRepeat -> Bool
$c/= :: SamplerRepeat -> SamplerRepeat -> Bool
== :: SamplerRepeat -> SamplerRepeat -> Bool
$c== :: SamplerRepeat -> SamplerRepeat -> Bool
Eq, Int -> SamplerRepeat
SamplerRepeat -> Int
SamplerRepeat -> [SamplerRepeat]
SamplerRepeat -> SamplerRepeat
SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
SamplerRepeat -> SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
(SamplerRepeat -> SamplerRepeat)
-> (SamplerRepeat -> SamplerRepeat)
-> (Int -> SamplerRepeat)
-> (SamplerRepeat -> Int)
-> (SamplerRepeat -> [SamplerRepeat])
-> (SamplerRepeat -> SamplerRepeat -> [SamplerRepeat])
-> (SamplerRepeat -> SamplerRepeat -> [SamplerRepeat])
-> (SamplerRepeat
-> SamplerRepeat -> SamplerRepeat -> [SamplerRepeat])
-> Enum SamplerRepeat
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: SamplerRepeat -> SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
$cenumFromThenTo :: SamplerRepeat -> SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
enumFromTo :: SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
$cenumFromTo :: SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
enumFromThen :: SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
$cenumFromThen :: SamplerRepeat -> SamplerRepeat -> [SamplerRepeat]
enumFrom :: SamplerRepeat -> [SamplerRepeat]
$cenumFrom :: SamplerRepeat -> [SamplerRepeat]
fromEnum :: SamplerRepeat -> Int
$cfromEnum :: SamplerRepeat -> Int
toEnum :: Int -> SamplerRepeat
$ctoEnum :: Int -> SamplerRepeat
pred :: SamplerRepeat -> SamplerRepeat
$cpred :: SamplerRepeat -> SamplerRepeat
succ :: SamplerRepeat -> SamplerRepeat
$csucc :: SamplerRepeat -> SamplerRepeat
Enum, Int -> SamplerRepeat -> ShowS
[SamplerRepeat] -> ShowS
SamplerRepeat -> String
(Int -> SamplerRepeat -> ShowS)
-> (SamplerRepeat -> String)
-> ([SamplerRepeat] -> ShowS)
-> Show SamplerRepeat
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SamplerRepeat] -> ShowS
$cshowList :: [SamplerRepeat] -> ShowS
show :: SamplerRepeat -> String
$cshow :: SamplerRepeat -> String
showsPrec :: Int -> SamplerRepeat -> ShowS
$cshowsPrec :: Int -> SamplerRepeat -> ShowS
Show)
data EdgeSample = EdgeSample
{ EdgeSample -> Float
_sampleX :: {-# UNPACK #-} !Float
, EdgeSample -> Float
_sampleY :: {-# UNPACK #-} !Float
, EdgeSample -> Float
_sampleAlpha :: {-# UNPACK #-} !Float
, EdgeSample -> Float
_sampleH :: {-# UNPACK #-} !Float
}
deriving Int -> EdgeSample -> ShowS
[EdgeSample] -> ShowS
EdgeSample -> String
(Int -> EdgeSample -> ShowS)
-> (EdgeSample -> String)
-> ([EdgeSample] -> ShowS)
-> Show EdgeSample
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EdgeSample] -> ShowS
$cshowList :: [EdgeSample] -> ShowS
show :: EdgeSample -> String
$cshow :: EdgeSample -> String
showsPrec :: Int -> EdgeSample -> ShowS
$cshowsPrec :: Int -> EdgeSample -> ShowS
Show
instance Storable EdgeSample where
sizeOf :: EdgeSample -> Int
sizeOf EdgeSample
_ = Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Float -> Int
forall a. Storable a => a -> Int
sizeOf (Float
0 :: Float)
alignment :: EdgeSample -> Int
alignment = EdgeSample -> Int
forall a. Storable a => a -> Int
sizeOf
{-# INLINE peek #-}
peek :: Ptr EdgeSample -> IO EdgeSample
peek Ptr EdgeSample
ptr = do
let q :: Ptr Float
q = Ptr EdgeSample -> Ptr Float
forall a b. Ptr a -> Ptr b
castPtr Ptr EdgeSample
ptr
Float
sx <- Ptr Float -> Int -> IO Float
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
q Int
0
Float
sy <- Ptr Float -> Int -> IO Float
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
q Int
1
Float
sa <- Ptr Float -> Int -> IO Float
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
q Int
2
Float
sh <- Ptr Float -> Int -> IO Float
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr Float
q Int
3
EdgeSample -> IO EdgeSample
forall (m :: * -> *) a. Monad m => a -> m a
return (EdgeSample -> IO EdgeSample) -> EdgeSample -> IO EdgeSample
forall a b. (a -> b) -> a -> b
$ Float -> Float -> Float -> Float -> EdgeSample
EdgeSample Float
sx Float
sy Float
sa Float
sh
{-# INLINE poke #-}
poke :: Ptr EdgeSample -> EdgeSample -> IO ()
poke Ptr EdgeSample
ptr (EdgeSample Float
sx Float
sy Float
sa Float
sh) = do
let q :: Ptr Float
q = Ptr EdgeSample -> Ptr Float
forall a b. Ptr a -> Ptr b
castPtr Ptr EdgeSample
ptr
Ptr Float -> Int -> Float -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
q Int
0 Float
sx
Ptr Float -> Int -> Float -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
q Int
1 Float
sy
Ptr Float -> Int -> Float -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
q Int
2 Float
sa
Ptr Float -> Int -> Float -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff Ptr Float
q Int
3 Float
sh
class Transformable a where
transform :: (Point -> Point) -> a -> a
transform Point -> Point
f = Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> (a -> Identity a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point -> Identity Point) -> a -> Identity a
forall a (m :: * -> *).
(Transformable a, Monad m) =>
(Point -> m Point) -> a -> m a
transformM (Point -> Identity Point
forall (m :: * -> *) a. Monad m => a -> m a
return (Point -> Identity Point)
-> (Point -> Point) -> Point -> Identity Point
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point -> Point
f)
transformM :: Monad m => (Point -> m Point) -> a -> m a
class PointFoldable a where
foldPoints :: (b -> Point -> b) -> b -> a -> b
instance Transformable Point where
{-# INLINE transform #-}
transform :: (Point -> Point) -> Point -> Point
transform Point -> Point
f = Point -> Point
f
{-# INLINE transformM #-}
transformM :: (Point -> m Point) -> Point -> m Point
transformM Point -> m Point
f = Point -> m Point
f
instance PointFoldable Point where
{-# INLINE foldPoints #-}
foldPoints :: (b -> Point -> b) -> b -> Point -> b
foldPoints b -> Point -> b
f = b -> Point -> b
f
data Line = Line
{ Line -> Point
_lineX0 :: {-# UNPACK #-} !Point
, Line -> Point
_lineX1 :: {-# UNPACK #-} !Point
}
deriving Line -> Line -> Bool
(Line -> Line -> Bool) -> (Line -> Line -> Bool) -> Eq Line
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Line -> Line -> Bool
$c/= :: Line -> Line -> Bool
== :: Line -> Line -> Bool
$c== :: Line -> Line -> Bool
Eq
instance Show Line where
show :: Line -> String
show (Line Point
a Point
b) =
String
"Line (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") ("
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
b String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
instance Transformable Line where
{-# INLINE transformM #-}
transformM :: (Point -> m Point) -> Line -> m Line
transformM Point -> m Point
f (Line Point
a Point
b) = Point -> Point -> Line
Line (Point -> Point -> Line) -> m Point -> m (Point -> Line)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Point -> m Point
f Point
a m (Point -> Line) -> m Point -> m Line
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
b
instance PointFoldable Line where
{-# INLINE foldPoints #-}
foldPoints :: (b -> Point -> b) -> b -> Line -> b
foldPoints b -> Point -> b
f b
acc (Line Point
a Point
b) = b -> Point -> b
f (b -> Point -> b
f b
acc Point
b) Point
a
data Bezier = Bezier
{
Bezier -> Point
_bezierX0 :: {-# UNPACK #-} !Point
, Bezier -> Point
_bezierX1 :: {-# UNPACK #-} !Point
, Bezier -> Point
_bezierX2 :: {-# UNPACK #-} !Point
}
deriving Bezier -> Bezier -> Bool
(Bezier -> Bezier -> Bool)
-> (Bezier -> Bezier -> Bool) -> Eq Bezier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Bezier -> Bezier -> Bool
$c/= :: Bezier -> Bezier -> Bool
== :: Bezier -> Bezier -> Bool
$c== :: Bezier -> Bezier -> Bool
Eq
instance Show Bezier where
show :: Bezier -> String
show (Bezier Point
a Point
b Point
c) =
String
"Bezier (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") ("
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
b String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") ("
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
c String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
instance Transformable Bezier where
{-# INLINE transform #-}
transform :: (Point -> Point) -> Bezier -> Bezier
transform Point -> Point
f (Bezier Point
a Point
b Point
c) = Point -> Point -> Point -> Bezier
Bezier (Point -> Point
f Point
a) (Point -> Point
f Point
b) (Point -> Bezier) -> Point -> Bezier
forall a b. (a -> b) -> a -> b
$ Point -> Point
f Point
c
{-# INLINE transformM #-}
transformM :: (Point -> m Point) -> Bezier -> m Bezier
transformM Point -> m Point
f (Bezier Point
a Point
b Point
c) = Point -> Point -> Point -> Bezier
Bezier (Point -> Point -> Point -> Bezier)
-> m Point -> m (Point -> Point -> Bezier)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Point -> m Point
f Point
a m (Point -> Point -> Bezier) -> m Point -> m (Point -> Bezier)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
b m (Point -> Bezier) -> m Point -> m Bezier
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
c
instance PointFoldable Bezier where
{-# INLINE foldPoints #-}
foldPoints :: (b -> Point -> b) -> b -> Bezier -> b
foldPoints b -> Point -> b
f b
acc (Bezier Point
a Point
b Point
c) =
(b -> Point -> b) -> b -> [Point] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' b -> Point -> b
f b
acc [Point
a, Point
b, Point
c]
data CubicBezier = CubicBezier
{
CubicBezier -> Point
_cBezierX0 :: {-# UNPACK #-} !Point
, CubicBezier -> Point
_cBezierX1 :: {-# UNPACK #-} !Point
, CubicBezier -> Point
_cBezierX2 :: {-# UNPACK #-} !Point
, CubicBezier -> Point
_cBezierX3 :: {-# UNPACK #-} !Point
}
deriving CubicBezier -> CubicBezier -> Bool
(CubicBezier -> CubicBezier -> Bool)
-> (CubicBezier -> CubicBezier -> Bool) -> Eq CubicBezier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CubicBezier -> CubicBezier -> Bool
$c/= :: CubicBezier -> CubicBezier -> Bool
== :: CubicBezier -> CubicBezier -> Bool
$c== :: CubicBezier -> CubicBezier -> Bool
Eq
instance Show CubicBezier where
show :: CubicBezier -> String
show (CubicBezier Point
a Point
b Point
c Point
d) =
String
"CubicBezier (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") ("
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
b String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") ("
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
c String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") ("
String -> ShowS
forall a. [a] -> [a] -> [a]
++ Point -> String
forall a. Show a => a -> String
show Point
d String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
instance Transformable CubicBezier where
{-# INLINE transform #-}
transform :: (Point -> Point) -> CubicBezier -> CubicBezier
transform Point -> Point
f (CubicBezier Point
a Point
b Point
c Point
d) =
Point -> Point -> Point -> Point -> CubicBezier
CubicBezier (Point -> Point
f Point
a) (Point -> Point
f Point
b) (Point -> Point
f Point
c) (Point -> CubicBezier) -> Point -> CubicBezier
forall a b. (a -> b) -> a -> b
$ Point -> Point
f Point
d
transformM :: (Point -> m Point) -> CubicBezier -> m CubicBezier
transformM Point -> m Point
f (CubicBezier Point
a Point
b Point
c Point
d) =
Point -> Point -> Point -> Point -> CubicBezier
CubicBezier (Point -> Point -> Point -> Point -> CubicBezier)
-> m Point -> m (Point -> Point -> Point -> CubicBezier)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Point -> m Point
f Point
a m (Point -> Point -> Point -> CubicBezier)
-> m Point -> m (Point -> Point -> CubicBezier)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
b m (Point -> Point -> CubicBezier)
-> m Point -> m (Point -> CubicBezier)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
c m (Point -> CubicBezier) -> m Point -> m CubicBezier
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
d
instance PointFoldable CubicBezier where
{-# INLINE foldPoints #-}
foldPoints :: (b -> Point -> b) -> b -> CubicBezier -> b
foldPoints b -> Point -> b
f b
acc (CubicBezier Point
a Point
b Point
c Point
d) =
(b -> Point -> b) -> b -> [Point] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' b -> Point -> b
f b
acc [Point
a, Point
b, Point
c, Point
d]
data Primitive
= LinePrim !Line
| BezierPrim !Bezier
| CubicBezierPrim !CubicBezier
deriving (Primitive -> Primitive -> Bool
(Primitive -> Primitive -> Bool)
-> (Primitive -> Primitive -> Bool) -> Eq Primitive
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Primitive -> Primitive -> Bool
$c/= :: Primitive -> Primitive -> Bool
== :: Primitive -> Primitive -> Bool
$c== :: Primitive -> Primitive -> Bool
Eq, Int -> Primitive -> ShowS
[Primitive] -> ShowS
Primitive -> String
(Int -> Primitive -> ShowS)
-> (Primitive -> String)
-> ([Primitive] -> ShowS)
-> Show Primitive
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Primitive] -> ShowS
$cshowList :: [Primitive] -> ShowS
show :: Primitive -> String
$cshow :: Primitive -> String
showsPrec :: Int -> Primitive -> ShowS
$cshowsPrec :: Int -> Primitive -> ShowS
Show)
class Primitivable a where
toPrim :: a -> Primitive
instance Primitivable Primitive where toPrim :: Primitive -> Primitive
toPrim = Primitive -> Primitive
forall a. a -> a
id
instance Primitivable Line where toPrim :: Line -> Primitive
toPrim = Line -> Primitive
LinePrim
instance Primitivable Bezier where toPrim :: Bezier -> Primitive
toPrim = Bezier -> Primitive
BezierPrim
instance Primitivable CubicBezier where toPrim :: CubicBezier -> Primitive
toPrim = CubicBezier -> Primitive
CubicBezierPrim
class Geometry a where
toPrimitives :: a -> [Primitive]
listToPrims :: (Foldable f) => f a -> [Primitive]
{-# INLINE listToPrims #-}
listToPrims = (a -> [Primitive]) -> [a] -> [Primitive]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
F.concatMap a -> [Primitive]
forall a. Geometry a => a -> [Primitive]
toPrimitives ([a] -> [Primitive]) -> (f a -> [a]) -> f a -> [Primitive]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList
instance Geometry Path where
{-# INLINE toPrimitives #-}
toPrimitives :: Path -> [Primitive]
toPrimitives = Path -> [Primitive]
pathToPrimitives
instance Geometry Primitive where
toPrimitives :: Primitive -> [Primitive]
toPrimitives Primitive
e = [Primitive
e]
{-# INLINE listToPrims #-}
listToPrims :: f Primitive -> [Primitive]
listToPrims = f Primitive -> [Primitive]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList
instance Geometry Line where
{-# INLINE toPrimitives #-}
toPrimitives :: Line -> [Primitive]
toPrimitives Line
e = [Line -> Primitive
forall a. Primitivable a => a -> Primitive
toPrim Line
e]
instance Geometry Bezier where
{-# INLINE toPrimitives #-}
toPrimitives :: Bezier -> [Primitive]
toPrimitives Bezier
e = [Bezier -> Primitive
forall a. Primitivable a => a -> Primitive
toPrim Bezier
e]
instance Geometry CubicBezier where
{-# INLINE toPrimitives #-}
toPrimitives :: CubicBezier -> [Primitive]
toPrimitives CubicBezier
e = [CubicBezier -> Primitive
forall a. Primitivable a => a -> Primitive
toPrim CubicBezier
e]
instance (Foldable f, Geometry a) => Geometry (f a) where
{-# INLINE toPrimitives #-}
toPrimitives :: f a -> [Primitive]
toPrimitives = f a -> [Primitive]
forall a (f :: * -> *).
(Geometry a, Foldable f) =>
f a -> [Primitive]
listToPrims
instance Transformable Primitive where
{-# INLINE transform #-}
transform :: (Point -> Point) -> Primitive -> Primitive
transform Point -> Point
f (LinePrim Line
l) = Line -> Primitive
LinePrim (Line -> Primitive) -> Line -> Primitive
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> Line -> Line
forall a. Transformable a => (Point -> Point) -> a -> a
transform Point -> Point
f Line
l
transform Point -> Point
f (BezierPrim Bezier
b) = Bezier -> Primitive
BezierPrim (Bezier -> Primitive) -> Bezier -> Primitive
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> Bezier -> Bezier
forall a. Transformable a => (Point -> Point) -> a -> a
transform Point -> Point
f Bezier
b
transform Point -> Point
f (CubicBezierPrim CubicBezier
c) = CubicBezier -> Primitive
CubicBezierPrim (CubicBezier -> Primitive) -> CubicBezier -> Primitive
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> CubicBezier -> CubicBezier
forall a. Transformable a => (Point -> Point) -> a -> a
transform Point -> Point
f CubicBezier
c
transformM :: (Point -> m Point) -> Primitive -> m Primitive
transformM Point -> m Point
f (LinePrim Line
l) = Line -> Primitive
LinePrim (Line -> Primitive) -> m Line -> m Primitive
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Point -> m Point) -> Line -> m Line
forall a (m :: * -> *).
(Transformable a, Monad m) =>
(Point -> m Point) -> a -> m a
transformM Point -> m Point
f Line
l
transformM Point -> m Point
f (BezierPrim Bezier
b) = Bezier -> Primitive
BezierPrim (Bezier -> Primitive) -> m Bezier -> m Primitive
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Point -> m Point) -> Bezier -> m Bezier
forall a (m :: * -> *).
(Transformable a, Monad m) =>
(Point -> m Point) -> a -> m a
transformM Point -> m Point
f Bezier
b
transformM Point -> m Point
f (CubicBezierPrim CubicBezier
c) = CubicBezier -> Primitive
CubicBezierPrim (CubicBezier -> Primitive) -> m CubicBezier -> m Primitive
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Point -> m Point) -> CubicBezier -> m CubicBezier
forall a (m :: * -> *).
(Transformable a, Monad m) =>
(Point -> m Point) -> a -> m a
transformM Point -> m Point
f CubicBezier
c
instance PointFoldable Primitive where
{-# INLINE foldPoints #-}
foldPoints :: (b -> Point -> b) -> b -> Primitive -> b
foldPoints b -> Point -> b
f b
acc = Primitive -> b
go
where go :: Primitive -> b
go (LinePrim Line
l) = (b -> Point -> b) -> b -> Line -> b
forall a b. PointFoldable a => (b -> Point -> b) -> b -> a -> b
foldPoints b -> Point -> b
f b
acc Line
l
go (BezierPrim Bezier
b) = (b -> Point -> b) -> b -> Bezier -> b
forall a b. PointFoldable a => (b -> Point -> b) -> b -> a -> b
foldPoints b -> Point -> b
f b
acc Bezier
b
go (CubicBezierPrim CubicBezier
c) = (b -> Point -> b) -> b -> CubicBezier -> b
forall a b. PointFoldable a => (b -> Point -> b) -> b -> a -> b
foldPoints b -> Point -> b
f b
acc CubicBezier
c
instance {-# OVERLAPPABLE #-} (Traversable f, Transformable a)
=> Transformable (f a) where
transform :: (Point -> Point) -> f a -> f a
transform Point -> Point
f = (a -> a) -> f a -> f a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Point -> Point) -> a -> a
forall a. Transformable a => (Point -> Point) -> a -> a
transform Point -> Point
f)
transformM :: (Point -> m Point) -> f a -> m (f a)
transformM Point -> m Point
f = (a -> m a) -> f a -> m (f a)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((Point -> m Point) -> a -> m a
forall a (m :: * -> *).
(Transformable a, Monad m) =>
(Point -> m Point) -> a -> m a
transformM Point -> m Point
f)
instance {-# OVERLAPPABLE #-} (Foldable f, PointFoldable a)
=> PointFoldable (f a) where
foldPoints :: (b -> Point -> b) -> b -> f a -> b
foldPoints b -> Point -> b
f = (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ((b -> Point -> b) -> b -> a -> b
forall a b. PointFoldable a => (b -> Point -> b) -> b -> a -> b
foldPoints b -> Point -> b
f)
type Producer a = [a] -> [a]
type Container a = DList a
containerOfFunction :: ([a] -> [a]) -> Container a
containerOfFunction :: ([a] -> [a]) -> Container a
containerOfFunction [a] -> [a]
f = [a] -> Container a
forall a. [a] -> DList a
fromList ([a] -> Container a) -> [a] -> Container a
forall a b. (a -> b) -> a -> b
$ [a] -> [a]
f []
containerOfList :: [a] -> Container a
containerOfList :: [a] -> Container a
containerOfList = [a] -> Container a
forall a. [a] -> DList a
fromList
listOfContainer :: Container a -> [a]
listOfContainer :: Container a -> [a]
listOfContainer = Container a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList
data Path = Path
{
Path -> Point
_pathOriginPoint :: Point
, Path -> Bool
_pathClose :: Bool
, Path -> [PathCommand]
_pathCommand :: [PathCommand]
}
deriving (Path -> Path -> Bool
(Path -> Path -> Bool) -> (Path -> Path -> Bool) -> Eq Path
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Path -> Path -> Bool
$c/= :: Path -> Path -> Bool
== :: Path -> Path -> Bool
$c== :: Path -> Path -> Bool
Eq, Int -> Path -> ShowS
[Path] -> ShowS
Path -> String
(Int -> Path -> ShowS)
-> (Path -> String) -> ([Path] -> ShowS) -> Show Path
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Path] -> ShowS
$cshowList :: [Path] -> ShowS
show :: Path -> String
$cshow :: Path -> String
showsPrec :: Int -> Path -> ShowS
$cshowsPrec :: Int -> Path -> ShowS
Show)
instance Transformable Path where
{-# INLINE transform #-}
transform :: (Point -> Point) -> Path -> Path
transform Point -> Point
f (Path Point
orig Bool
close [PathCommand]
rest) =
Point -> Bool -> [PathCommand] -> Path
Path (Point -> Point
f Point
orig) Bool
close ((Point -> Point) -> [PathCommand] -> [PathCommand]
forall a. Transformable a => (Point -> Point) -> a -> a
transform Point -> Point
f [PathCommand]
rest)
transformM :: (Point -> m Point) -> Path -> m Path
transformM Point -> m Point
f (Path Point
orig Bool
close [PathCommand]
rest) =
Point -> Bool -> [PathCommand] -> Path
Path (Point -> Bool -> [PathCommand] -> Path)
-> m Point -> m (Bool -> [PathCommand] -> Path)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Point -> m Point
f Point
orig m (Bool -> [PathCommand] -> Path)
-> m Bool -> m ([PathCommand] -> Path)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
close m ([PathCommand] -> Path) -> m [PathCommand] -> m Path
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Point -> m Point) -> [PathCommand] -> m [PathCommand]
forall a (m :: * -> *).
(Transformable a, Monad m) =>
(Point -> m Point) -> a -> m a
transformM Point -> m Point
f [PathCommand]
rest
instance PointFoldable Path where
{-# INLINE foldPoints #-}
foldPoints :: (b -> Point -> b) -> b -> Path -> b
foldPoints b -> Point -> b
f b
acc (Path Point
o Bool
_ [PathCommand]
rest) =
(b -> Point -> b) -> b -> [PathCommand] -> b
forall a b. PointFoldable a => (b -> Point -> b) -> b -> a -> b
foldPoints b -> Point -> b
f (b -> Point -> b
f b
acc Point
o) [PathCommand]
rest
data PathCommand
=
PathLineTo Point
| PathQuadraticBezierCurveTo Point Point
| PathCubicBezierCurveTo Point Point Point
deriving (PathCommand -> PathCommand -> Bool
(PathCommand -> PathCommand -> Bool)
-> (PathCommand -> PathCommand -> Bool) -> Eq PathCommand
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PathCommand -> PathCommand -> Bool
$c/= :: PathCommand -> PathCommand -> Bool
== :: PathCommand -> PathCommand -> Bool
$c== :: PathCommand -> PathCommand -> Bool
Eq, Int -> PathCommand -> ShowS
[PathCommand] -> ShowS
PathCommand -> String
(Int -> PathCommand -> ShowS)
-> (PathCommand -> String)
-> ([PathCommand] -> ShowS)
-> Show PathCommand
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PathCommand] -> ShowS
$cshowList :: [PathCommand] -> ShowS
show :: PathCommand -> String
$cshow :: PathCommand -> String
showsPrec :: Int -> PathCommand -> ShowS
$cshowsPrec :: Int -> PathCommand -> ShowS
Show)
instance Transformable PathCommand where
transform :: (Point -> Point) -> PathCommand -> PathCommand
transform Point -> Point
f (PathLineTo Point
p) = Point -> PathCommand
PathLineTo (Point -> PathCommand) -> Point -> PathCommand
forall a b. (a -> b) -> a -> b
$ Point -> Point
f Point
p
transform Point -> Point
f (PathQuadraticBezierCurveTo Point
p1 Point
p2) =
Point -> Point -> PathCommand
PathQuadraticBezierCurveTo (Point -> Point
f Point
p1) (Point -> PathCommand) -> Point -> PathCommand
forall a b. (a -> b) -> a -> b
$ Point -> Point
f Point
p2
transform Point -> Point
f (PathCubicBezierCurveTo Point
p1 Point
p2 Point
p3) =
Point -> Point -> Point -> PathCommand
PathCubicBezierCurveTo (Point -> Point
f Point
p1) (Point -> Point
f Point
p2) (Point -> PathCommand) -> Point -> PathCommand
forall a b. (a -> b) -> a -> b
$ Point -> Point
f Point
p3
transformM :: (Point -> m Point) -> PathCommand -> m PathCommand
transformM Point -> m Point
f (PathLineTo Point
p) = Point -> PathCommand
PathLineTo (Point -> PathCommand) -> m Point -> m PathCommand
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Point -> m Point
f Point
p
transformM Point -> m Point
f (PathQuadraticBezierCurveTo Point
p1 Point
p2) =
Point -> Point -> PathCommand
PathQuadraticBezierCurveTo (Point -> Point -> PathCommand)
-> m Point -> m (Point -> PathCommand)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Point -> m Point
f Point
p1 m (Point -> PathCommand) -> m Point -> m PathCommand
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
p2
transformM Point -> m Point
f (PathCubicBezierCurveTo Point
p1 Point
p2 Point
p3) =
Point -> Point -> Point -> PathCommand
PathCubicBezierCurveTo (Point -> Point -> Point -> PathCommand)
-> m Point -> m (Point -> Point -> PathCommand)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Point -> m Point
f Point
p1 m (Point -> Point -> PathCommand)
-> m Point -> m (Point -> PathCommand)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
p2 m (Point -> PathCommand) -> m Point -> m PathCommand
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Point -> m Point
f Point
p3
instance PointFoldable PathCommand where
foldPoints :: (b -> Point -> b) -> b -> PathCommand -> b
foldPoints b -> Point -> b
f b
acc (PathLineTo Point
p) = b -> Point -> b
f b
acc Point
p
foldPoints b -> Point -> b
f b
acc (PathQuadraticBezierCurveTo Point
p1 Point
p2) =
b -> Point -> b
f (b -> Point -> b
f b
acc Point
p1) Point
p2
foldPoints b -> Point -> b
f b
acc (PathCubicBezierCurveTo Point
p1 Point
p2 Point
p3) =
(b -> Point -> b) -> b -> [Point] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' b -> Point -> b
f b
acc [Point
p1, Point
p2, Point
p3]
pathToPrimitives :: Path -> [Primitive]
pathToPrimitives :: Path -> [Primitive]
pathToPrimitives (Path Point
origin Bool
needClosing [PathCommand]
commands) = Point -> [PathCommand] -> [Primitive]
go Point
origin [PathCommand]
commands
where
go :: Point -> [PathCommand] -> [Primitive]
go Point
prev [] | Point
prev Point -> Point -> Bool
forall a. Eq a => a -> a -> Bool
/= Point
origin Bool -> Bool -> Bool
&& Bool
needClosing = [Line -> Primitive
LinePrim (Line -> Primitive) -> Line -> Primitive
forall a b. (a -> b) -> a -> b
$ Point -> Point -> Line
Line Point
prev Point
origin]
go Point
_ [] = []
go Point
prev (PathLineTo Point
to : [PathCommand]
xs) =
Line -> Primitive
LinePrim (Point -> Point -> Line
Line Point
prev Point
to) Primitive -> [Primitive] -> [Primitive]
forall a. a -> [a] -> [a]
: Point -> [PathCommand] -> [Primitive]
go Point
to [PathCommand]
xs
go Point
prev (PathQuadraticBezierCurveTo Point
c1 Point
to : [PathCommand]
xs) =
Bezier -> Primitive
BezierPrim (Point -> Point -> Point -> Bezier
Bezier Point
prev Point
c1 Point
to) Primitive -> [Primitive] -> [Primitive]
forall a. a -> [a] -> [a]
: Point -> [PathCommand] -> [Primitive]
go Point
to [PathCommand]
xs
go Point
prev (PathCubicBezierCurveTo Point
c1 Point
c2 Point
to : [PathCommand]
xs) =
CubicBezier -> Primitive
CubicBezierPrim (Point -> Point -> Point -> Point -> CubicBezier
CubicBezier Point
prev Point
c1 Point
c2 Point
to) Primitive -> [Primitive] -> [Primitive]
forall a. a -> [a] -> [a]
: Point -> [PathCommand] -> [Primitive]
go Point
to [PathCommand]
xs
firstTangeantOf :: Primitive -> Vector
firstTangeantOf :: Primitive -> Point
firstTangeantOf Primitive
p = case Primitive
p of
LinePrim (Line Point
p0 Point
p1) -> Point
p1 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p0
BezierPrim (Bezier Point
p0 Point
p1 Point
p2) ->
(Point
p1 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p0) Point -> Point -> Point
forall p. Epsilon p => p -> p -> p
`ifBigEnough` (Point
p2 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p1)
CubicBezierPrim (CubicBezier Point
p0 Point
p1 Point
p2 Point
_) ->
(Point
p1 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p0) Point -> Point -> Point
forall p. Epsilon p => p -> p -> p
`ifBigEnough` (Point
p2 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p1)
where
ifBigEnough :: p -> p -> p
ifBigEnough p
a p
b | p -> Bool
forall a. Epsilon a => a -> Bool
nearZero p
a = p
b
| Bool
otherwise = p
a
lastTangeantOf :: Primitive -> Vector
lastTangeantOf :: Primitive -> Point
lastTangeantOf Primitive
p = case Primitive
p of
LinePrim (Line Point
p0 Point
p1) -> Point
p1 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p0
BezierPrim (Bezier Point
_ Point
p1 Point
p2) -> Point
p2 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p1
CubicBezierPrim (CubicBezier Point
_ Point
_ Point
p2 Point
p3) -> Point
p3 Point -> Point -> Point
forall (f :: * -> *) a. (Additive f, Num a) => f a -> f a -> f a
^-^ Point
p2
firstPointOf :: Primitive -> Point
firstPointOf :: Primitive -> Point
firstPointOf Primitive
p = case Primitive
p of
LinePrim (Line Point
p0 Point
_) -> Point
p0
BezierPrim (Bezier Point
p0 Point
_ Point
_) -> Point
p0
CubicBezierPrim (CubicBezier Point
p0 Point
_ Point
_ Point
_) -> Point
p0
lastPointOf :: Primitive -> Point
lastPointOf :: Primitive -> Point
lastPointOf Primitive
p = case Primitive
p of
LinePrim (Line Point
_ Point
p0) -> Point
p0
BezierPrim (Bezier Point
_ Point
_ Point
p0) -> Point
p0
CubicBezierPrim (CubicBezier Point
_ Point
_ Point
_ Point
p0) -> Point
p0
resplit :: [Primitive] -> [[Primitive]]
resplit :: [Primitive] -> [[Primitive]]
resplit = ([Primitive] -> [[Primitive]] -> [[Primitive]])
-> ([Primitive], [[Primitive]]) -> [[Primitive]]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (:) (([Primitive], [[Primitive]]) -> [[Primitive]])
-> ([Primitive] -> ([Primitive], [[Primitive]]))
-> [Primitive]
-> [[Primitive]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Primitive] -> ([Primitive], [[Primitive]])
go where
go :: [Primitive] -> ([Primitive], [[Primitive]])
go [] = ([], [])
go (Primitive
x:xs :: [Primitive]
xs@(Primitive
y:[Primitive]
_)) | Primitive -> Point
lastPointOf Primitive
x Point -> Point -> Bool
`isDistingableFrom` Primitive -> Point
firstPointOf Primitive
y =
([Primitive
x], [Primitive]
after[Primitive] -> [[Primitive]] -> [[Primitive]]
forall a. a -> [a] -> [a]
:[[Primitive]]
rest) where ([Primitive]
after, [[Primitive]]
rest) = [Primitive] -> ([Primitive], [[Primitive]])
go [Primitive]
xs
go (Primitive
x:[Primitive]
xs) = (Primitive
xPrimitive -> [Primitive] -> [Primitive]
forall a. a -> [a] -> [a]
:[Primitive]
curr, [[Primitive]]
rest) where ([Primitive]
curr, [[Primitive]]
rest) = [Primitive] -> ([Primitive], [[Primitive]])
go [Primitive]
xs