{-# LANGUAGE UndecidableInstances       #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE AllowAmbiguousTypes          #-}
{-# LANGUAGE QuantifiedConstraints          #-}
--------------------------------------------------------------------------------
-- |
-- Module      :  HGeometry.Miso.Svg.Draw
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- Draw geometric objects to Svg files through miso.
--
-- This uses the newer API common with ipe
--
--------------------------------------------------------------------------------
module HGeometry.Miso.Svg.Draw
  ( Svg
  , SVG
  , module Ipe.Draw
  ) where

import           HGeometry.Number.Radical
import           Prelude hiding (sqrt)
import           Data.List.NonEmpty (NonEmpty(..))
import           Control.Lens
import           Data.Kind (Type)
import           HGeometry.PolyLine
import           HGeometry.Point
import           HGeometry.Ball
import           HGeometry.Box
import           HGeometry.LineSegment
import           Data.Default
import           Ipe.Attributes
import           Ipe.Color (black)
import           Ipe.Draw
import           Ipe.Content
import           Miso (View)
import           HGeometry.Polygon
import           HGeometry.Properties
import qualified HGeometry.Miso.Svg as Svg
import           Miso.String (ToMisoString(..), ms, intercalate)
import qualified Miso.Svg as Elem
import qualified Miso.Svg.Property as Prop
import           HGeometry.BezierSpline
import qualified Miso
import           Data.Void

--------------------------------------------------------------------------------

-- | The Svg backend; which renders to Svg using Miso
type data Svg (model :: Type) (action :: Type)
-- TODO: I think we can even leave out the model;

-- | Static Svg
type SVG = Svg () Void

type instance Rendered (Svg model action) = [View () () model action]


--------------------------------------------------------------------------------

instance ( Point_ vertex 2 (NumType vertex)
         , ToMisoString (NumType vertex)
         , SimplePolygon_ (SimplePolygonF f vertex) vertex (NumType vertex)
         ) => IsDrawable (Svg model action) (SimplePolygonF f vertex) where
  type AttrOf (Svg model action) (SimplePolygonF f vertex) = PathAttributes (NumType vertex)
  draw :: [Attr (Svg model action) (SimplePolygonF f vertex)]
-> SimplePolygonF f vertex -> Rendered (Svg model action)
draw [Attr (Svg model action) (SimplePolygonF f vertex)]
ats SimplePolygonF f vertex
poly = [ SimplePolygonF f vertex
-> [Attribute model action] -> View () () model action
forall simplePolygon point r model action context props.
(SimplePolygon_ simplePolygon point r, ToMisoString r) =>
simplePolygon
-> [Attribute model action] -> View context props model action
Svg.dSimplePolygon SimplePolygonF f vertex
poly (PathAttributesF (NumType vertex) Maybe -> [Attribute model action]
forall model.
PathAttributesF (NumType vertex) Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs (PathAttributesF (NumType vertex) Maybe
 -> [Attribute model action])
-> PathAttributesF (NumType vertex) Maybe
-> [Attribute model action]
forall a b. (a -> b) -> a -> b
$ [PathAttributesF (NumType vertex) Maybe
 -> PathAttributesF (NumType vertex) Maybe]
-> PathAttributesF (NumType vertex) Maybe
forall at. Default at => [at -> at] -> at
apply [PathAttributesF (NumType vertex) Maybe
 -> PathAttributesF (NumType vertex) Maybe]
[Attr (Svg model action) (SimplePolygonF f vertex)]
ats)
                  ]

instance ( Point_ vertex 2 (NumType vertex)
         , ToMisoString (NumType vertex)
         , PolyLine_ (PolyLineF f vertex) vertex
         ) => IsDrawable (Svg model action) (PolyLineF f vertex) where
  type AttrOf (Svg model action) (PolyLineF f vertex) = PathAttributes (NumType vertex)
  draw :: [Attr (Svg model action) (PolyLineF f vertex)]
-> PolyLineF f vertex -> Rendered (Svg model action)
draw [Attr (Svg model action) (PolyLineF f vertex)]
ats PolyLineF f vertex
poly = [ PolyLineF f vertex
-> [Attribute model action] -> View () () model action
forall polyLine point r model action context props.
(PolyLine_ polyLine point, Point_ point 2 r, ToMisoString r) =>
polyLine
-> [Attribute model action] -> View context props model action
Svg.dPolyLine PolyLineF f vertex
poly (PathAttributesF (NumType vertex) Maybe -> [Attribute model action]
forall model.
PathAttributesF (NumType vertex) Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs (PathAttributesF (NumType vertex) Maybe
 -> [Attribute model action])
-> PathAttributesF (NumType vertex) Maybe
-> [Attribute model action]
forall a b. (a -> b) -> a -> b
$ [PathAttributesF (NumType vertex) Maybe
 -> PathAttributesF (NumType vertex) Maybe]
-> PathAttributesF (NumType vertex) Maybe
forall at. Default at => [at -> at] -> at
apply [PathAttributesF (NumType vertex) Maybe
 -> PathAttributesF (NumType vertex) Maybe]
[Attr (Svg model action) (PolyLineF f vertex)]
ats) ]


instance ( Point_ vertex 2 (NumType vertex)
         , ToMisoString (NumType vertex)
         , EndPoint_ (endPoint vertex), IxValue (endPoint vertex) ~ vertex
         ) => IsDrawable (Svg model action) (LineSegment endPoint vertex) where
  type AttrOf (Svg model action) (LineSegment endPoint vertex) = PathAttributes (NumType vertex)
  draw :: [Attr (Svg model action) (LineSegment endPoint vertex)]
-> LineSegment endPoint vertex -> Rendered (Svg model action)
draw [Attr (Svg model action) (LineSegment endPoint vertex)]
ats LineSegment endPoint vertex
seg = [ LineSegment endPoint vertex
-> [Attribute model action] -> View () () model action
forall lineSegment point r model action context props.
(LineSegment_ lineSegment point, Point_ point 2 r,
 ToMisoString r) =>
lineSegment
-> [Attribute model action] -> View context props model action
Svg.dLineSegment LineSegment endPoint vertex
seg (PathAttributesF (NumType vertex) Maybe -> [Attribute model action]
forall model.
PathAttributesF (NumType vertex) Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs (PathAttributesF (NumType vertex) Maybe
 -> [Attribute model action])
-> PathAttributesF (NumType vertex) Maybe
-> [Attribute model action]
forall a b. (a -> b) -> a -> b
$ [PathAttributesF (NumType vertex) Maybe
 -> PathAttributesF (NumType vertex) Maybe]
-> PathAttributesF (NumType vertex) Maybe
forall at. Default at => [at -> at] -> at
apply [PathAttributesF (NumType vertex) Maybe
 -> PathAttributesF (NumType vertex) Maybe]
[Attr (Svg model action) (LineSegment endPoint vertex)]
ats) ]


instance ( ToMisoString r
         ) => IsDrawable (Svg model action) (Point 2 r) where
  type AttrOf (Svg model action) (Point 2 r) = SymbolAttributes r
  draw :: [Attr (Svg model action) (Point 2 r)]
-> Point 2 r -> Rendered (Svg model action)
draw [Attr (Svg model action) (Point 2 r)]
ats Point 2 r
p = [ [Attribute model action] -> View () () model action
forall model action context props.
[Attribute model action] -> View context props model action
Elem.ellipse_ ([ MisoString -> Attribute model action
forall model action. MisoString -> Attribute model action
Prop.cx_ (r -> MisoString
forall str. ToMisoString str => str -> MisoString
ms (r -> MisoString) -> r -> MisoString
forall a b. (a -> b) -> a -> b
$ Point 2 r
pPoint 2 r -> Getting r (Point 2 r) r -> r
forall s a. s -> Getting a s a -> a
^.Getting r (Point 2 r) r
forall (d :: Nat) point r.
(1 <= d, Point_ point d r) =>
IndexedLens' Int point r
IndexedLens' Int (Point 2 r) r
xCoord), MisoString -> Attribute model action
forall model action. MisoString -> Attribute model action
Prop.cy_ (r -> MisoString
forall str. ToMisoString str => str -> MisoString
ms (r -> MisoString) -> r -> MisoString
forall a b. (a -> b) -> a -> b
$ Point 2 r
pPoint 2 r -> Getting r (Point 2 r) r -> r
forall s a. s -> Getting a s a -> a
^.Getting r (Point 2 r) r
forall (d :: Nat) point r.
(2 <= d, Point_ point d r) =>
IndexedLens' Int point r
IndexedLens' Int (Point 2 r) r
yCoord)
                                , MisoString -> Attribute model action
forall model action. MisoString -> Attribute model action
Prop.rx_ MisoString
"2", MisoString -> Attribute model action
forall model action. MisoString -> Attribute model action
Prop.ry_ MisoString
"2"
                                ] [Attribute model action]
-> [Attribute model action] -> [Attribute model action]
forall a. Semigroup a => a -> a -> a
<> SymbolAttributesF r Maybe -> [Attribute model action]
forall model. SymbolAttributesF r Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs ([SymbolAttributesF r Maybe -> SymbolAttributesF r Maybe]
-> SymbolAttributesF r Maybe
forall at. Default at => [at -> at] -> at
apply [SymbolAttributesF r Maybe -> SymbolAttributesF r Maybe]
[Attr (Svg model action) (Point 2 r)]
ats))
               ]

instance (Point_ point 2 r, Fractional r, ToMisoString r, r ~ NumType point
         ) => IsDrawable (Svg model action) (CubicBezier point) where
  type AttrOf (Svg model action) (CubicBezier point) = PathAttributes (NumType point)
  draw :: [Attr (Svg model action) (CubicBezier point)]
-> CubicBezier point -> Rendered (Svg model action)
draw [Attr (Svg model action) (CubicBezier point)]
ats (BezierSpline Vector 4 point
vs) = [ [Attribute model action] -> View () () model action
forall model action context props.
[Attribute model action] -> View context props model action
Elem.path_ ([ MisoString -> Attribute model action
forall model action. MisoString -> Attribute model action
Prop.d_ MisoString
str
                                             ] [Attribute model action]
-> [Attribute model action] -> [Attribute model action]
forall a. Semigroup a => a -> a -> a
<> PathAttributesF r Maybe -> [Attribute model action]
forall model. PathAttributesF r Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs ([PathAttributesF r Maybe -> PathAttributesF r Maybe]
-> PathAttributesF r Maybe -> PathAttributesF r Maybe
forall at. [at -> at] -> at -> at
applyWith [PathAttributesF r Maybe -> PathAttributesF r Maybe]
[Attr (Svg model action) (CubicBezier point)]
ats
                                                                     (PathAttributesF r Maybe -> PathAttributesF r Maybe)
-> PathAttributesF r Maybe -> PathAttributesF r Maybe
forall a b. (a -> b) -> a -> b
$ PathAttributesF r Maybe
forall a. Default a => a
defPathAttributesF r Maybe
-> (PathAttributesF r Maybe -> PathAttributesF r Maybe)
-> PathAttributesF r Maybe
forall a b. a -> (a -> b) -> b
&(Maybe (IpeColor r) -> Identity (Maybe (IpeColor r)))
-> PathAttributesF r Maybe -> Identity (PathAttributesF r Maybe)
forall s a. HasStroke s a => Lens' s a
Lens' (PathAttributesF r Maybe) (Maybe (IpeColor r))
stroke ((Maybe (IpeColor r) -> Identity (Maybe (IpeColor r)))
 -> PathAttributesF r Maybe -> Identity (PathAttributesF r Maybe))
-> Maybe (IpeColor r)
-> PathAttributesF r Maybe
-> PathAttributesF r Maybe
forall s t a b. ASetter s t a b -> b -> s -> t
.~ IpeColor r -> Maybe (IpeColor r)
forall a. a -> Maybe a
Just IpeColor r
forall r. IpeColor r
black
                                                                    )
                                            )
                               ]
    where
      str :: MisoString
str = let Point 2 r
v :| [Point 2 r]
rest = Getting (NonEmptyDList (Point 2 r)) (Vector 4 point) (Point 2 r)
-> Vector 4 point -> NonEmpty (Point 2 r)
forall a s. Getting (NonEmptyDList a) s a -> s -> NonEmpty a
toNonEmptyOf ((point -> Const (NonEmptyDList (Point 2 r)) point)
-> Vector 4 point
-> Const (NonEmptyDList (Point 2 r)) (Vector 4 point)
forall (f :: * -> *) a b.
Traversable1 f =>
IndexedTraversal1 Int (f a) (f b) a b
IndexedTraversal1 Int (Vector 4 point) (Vector 4 point) point point
traversed1((point -> Const (NonEmptyDList (Point 2 r)) point)
 -> Vector 4 point
 -> Const (NonEmptyDList (Point 2 r)) (Vector 4 point))
-> ((Point 2 r -> Const (NonEmptyDList (Point 2 r)) (Point 2 r))
    -> point -> Const (NonEmptyDList (Point 2 r)) point)
-> Getting (NonEmptyDList (Point 2 r)) (Vector 4 point) (Point 2 r)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Point 2 r -> Const (NonEmptyDList (Point 2 r)) (Point 2 r))
-> point -> Const (NonEmptyDList (Point 2 r)) point
forall point (d :: Nat) r.
Point_ point d r =>
Lens' point (Point d r)
Lens' point (Point 2 r)
asPoint) Vector 4 point
vs
            in MisoString
"M " MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> Point 2 r -> MisoString
forall {str}. ToMisoString str => Point 2 str -> MisoString
toStr Point 2 r
v MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
" C " MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString -> [MisoString] -> MisoString
intercalate MisoString
", " [ Point 2 r -> MisoString
forall {str}. ToMisoString str => Point 2 str -> MisoString
toStr Point 2 r
w | Point 2 r
w <- [Point 2 r]
rest ]
      toStr :: Point 2 str -> MisoString
toStr (Point2 str
x str
y) = str -> MisoString
forall str. ToMisoString str => str -> MisoString
ms str
x MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> MisoString
" " MisoString -> MisoString -> MisoString
forall a. Semigroup a => a -> a -> a
<> str -> MisoString
forall str. ToMisoString str => str -> MisoString
ms str
y


instance ToMisoString r => IsDrawable (Svg model action) (TextLabel r) where
  type AttrOf (Svg model action) (TextLabel r) = TextAttributes r
  draw :: [Attr (Svg model action) (TextLabel r)]
-> TextLabel r -> Rendered (Svg model action)
draw [Attr (Svg model action) (TextLabel r)]
ats (Label MisoString
txt Point 2 r
loc) = [ [Attribute model action]
-> [View () () model action] -> View () () model action
forall model action context props.
[Attribute model action]
-> [View context props model action]
-> View context props model action
Elem.text_ ([ MisoString -> Attribute model action
forall model action. MisoString -> Attribute model action
Prop.x_ (Point 2 r
locPoint 2 r
-> Getting MisoString (Point 2 r) MisoString -> MisoString
forall s a. s -> Getting a s a -> a
^.(r -> Const MisoString r)
-> Point 2 r -> Const MisoString (Point 2 r)
forall (d :: Nat) point r.
(1 <= d, Point_ point d r) =>
IndexedLens' Int point r
IndexedLens' Int (Point 2 r) r
xCoord((r -> Const MisoString r)
 -> Point 2 r -> Const MisoString (Point 2 r))
-> ((MisoString -> Const MisoString MisoString)
    -> r -> Const MisoString r)
-> Getting MisoString (Point 2 r) MisoString
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(r -> MisoString)
-> (MisoString -> Const MisoString MisoString)
-> r
-> Const MisoString r
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to r -> MisoString
forall str. ToMisoString str => str -> MisoString
ms)
                                           , MisoString -> Attribute model action
forall model action. MisoString -> Attribute model action
Prop.y_ (Point 2 r
locPoint 2 r
-> Getting MisoString (Point 2 r) MisoString -> MisoString
forall s a. s -> Getting a s a -> a
^.(r -> Const MisoString r)
-> Point 2 r -> Const MisoString (Point 2 r)
forall (d :: Nat) point r.
(2 <= d, Point_ point d r) =>
IndexedLens' Int point r
IndexedLens' Int (Point 2 r) r
yCoord((r -> Const MisoString r)
 -> Point 2 r -> Const MisoString (Point 2 r))
-> ((MisoString -> Const MisoString MisoString)
    -> r -> Const MisoString r)
-> Getting MisoString (Point 2 r) MisoString
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(r -> MisoString)
-> (MisoString -> Const MisoString MisoString)
-> r
-> Const MisoString r
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to r -> MisoString
forall str. ToMisoString str => str -> MisoString
ms)
                                           ] [Attribute model action]
-> [Attribute model action] -> [Attribute model action]
forall a. Semigroup a => a -> a -> a
<> TextAttributesF r Maybe -> [Attribute model action]
forall model. TextAttributesF r Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs ([TextAttributesF r Maybe -> TextAttributesF r Maybe]
-> TextAttributesF r Maybe
forall at. Default at => [at -> at] -> at
apply [TextAttributesF r Maybe -> TextAttributesF r Maybe]
[Attr (Svg model action) (TextLabel r)]
ats)
                                          )
                                          [ MisoString -> View () () model action
forall context props model action.
MisoString -> View context props model action
Miso.text (MisoString -> View () () model action)
-> MisoString -> View () () model action
forall a b. (a -> b) -> a -> b
$ MisoString -> MisoString
forall str. ToMisoString str => str -> MisoString
ms MisoString
txt]
                             ]
  -- TODO: I think I should just not use TextAttributes, but a custom
  -- SvgTextAttributes type

instance ( Point_ center 2 r, Radical r
         , ToMisoString r, r ~ NumType center
         ) => IsDrawable (Svg model action) (Circle center) where
  type AttrOf (Svg model action) (Circle center) = PathAttributes (NumType center)
  draw :: [Attr (Svg model action) (Circle center)]
-> Circle center -> Rendered (Svg model action)
draw [Attr (Svg model action) (Circle center)]
ats Circle center
c = [ Circle center
-> [Attribute model action] -> View () () model action
forall point r model action context props.
(Point_ point 2 r, ToMisoString r, Radical r) =>
Circle point
-> [Attribute model action] -> View context props model action
Svg.dCircle Circle center
c (PathAttributesF r Maybe -> [Attribute model action]
forall model. PathAttributesF r Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs (PathAttributesF r Maybe -> [Attribute model action])
-> PathAttributesF r Maybe -> [Attribute model action]
forall a b. (a -> b) -> a -> b
$ [PathAttributesF r Maybe -> PathAttributesF r Maybe]
-> PathAttributesF r Maybe
forall at. Default at => [at -> at] -> at
apply [PathAttributesF r Maybe -> PathAttributesF r Maybe]
[Attr (Svg model action) (Circle center)]
ats) ]

instance ( Point_ center 2 r, Radical r
         , ToMisoString r, r ~ NumType center, Radical r, Fractional r
         ) => IsDrawable (Svg model action) (Disk center) where
  type AttrOf (Svg model action) (Disk center) = PathAttributes (NumType center)
  draw :: [Attr (Svg model action) (Disk center)]
-> Disk center -> Rendered (Svg model action)
draw [Attr (Svg model action) (Disk center)]
ats Disk center
c = [ Disk center -> [Attribute model action] -> View () () model action
forall disk point r model action context props.
(Disk_ disk point, ConstructableBall_ disk point, Point_ point 2 r,
 ToMisoString r, Radical r) =>
disk -> [Attribute model action] -> View context props model action
Svg.dDisk Disk center
c (PathAttributesF r Maybe -> [Attribute model action]
forall model. PathAttributesF r Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs (PathAttributesF r Maybe -> [Attribute model action])
-> PathAttributesF r Maybe -> [Attribute model action]
forall a b. (a -> b) -> a -> b
$ [PathAttributesF r Maybe -> PathAttributesF r Maybe]
-> PathAttributesF r Maybe
forall at. Default at => [at -> at] -> at
apply [PathAttributesF r Maybe -> PathAttributesF r Maybe]
[Attr (Svg model action) (Disk center)]
ats) ]

instance ( Point_ corner 2 r
         , ToMisoString r, Num r, r ~ NumType corner
         ) => IsDrawable (Svg model action) (Rectangle corner) where
  type AttrOf (Svg model action) (Rectangle corner) = PathAttributes (NumType corner)
  draw :: [Attr (Svg model action) (Rectangle corner)]
-> Rectangle corner -> Rendered (Svg model action)
draw [Attr (Svg model action) (Rectangle corner)]
ats Rectangle corner
r = [ Rectangle corner
-> [Attribute model action] -> View () () model action
forall rectangle point r model action context props.
(Rectangle_ rectangle point, Point_ point 2 r, ToMisoString r,
 Num r) =>
rectangle
-> [Attribute model action] -> View context props model action
Svg.dRectangle Rectangle corner
r (PathAttributesF r Maybe -> [Attribute model action]
forall model. PathAttributesF r Maybe -> [Attribute model action]
forall (ats :: (* -> *) -> *) action model.
SvgWriteAttributes ats action =>
ats Maybe -> [Attribute model action]
Svg.svgWriteAttrs (PathAttributesF r Maybe -> [Attribute model action])
-> PathAttributesF r Maybe -> [Attribute model action]
forall a b. (a -> b) -> a -> b
$ [PathAttributesF r Maybe -> PathAttributesF r Maybe]
-> PathAttributesF r Maybe
forall at. Default at => [at -> at] -> at
apply [PathAttributesF r Maybe -> PathAttributesF r Maybe]
[Attr (Svg model action) (Rectangle corner)]
ats) ]


-- | Helper function to apply attributes
apply :: Default at => [at -> at] -> at
apply :: forall at. Default at => [at -> at] -> at
apply = ([at -> at] -> at -> at) -> at -> [at -> at] -> at
forall a b c. (a -> b -> c) -> b -> a -> c
flip [at -> at] -> at -> at
forall at. [at -> at] -> at -> at
applyWith at
forall a. Default a => a
def

applyWith      :: [at -> at] -> at -> at
applyWith :: forall at. [at -> at] -> at -> at
applyWith [at -> at]
fs at
z = (at -> (at -> at) -> at) -> at -> [at -> at] -> at
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (((at -> at) -> at -> at) -> at -> (at -> at) -> at
forall a b c. (a -> b -> c) -> b -> a -> c
flip (at -> at) -> at -> at
forall a b. (a -> b) -> a -> b
($)) at
z [at -> at]
fs