module Constructors where


data Foo
    = Bar
    | Baz
    | Quux Foo Int

newtype Norf = Norf (Foo, [Foo], Foo)


bar, baz, quux :: Foo
bar :: Foo
bar = Foo
Bar
baz :: Foo
baz = Foo
Baz
quux :: Foo
quux = Foo -> Int -> Foo
Quux Foo
quux 0


unfoo :: Foo -> Int
unfoo :: Foo -> Int
unfoo Bar = 0
unfoo Baz = 0
unfoo (Quux foo :: Foo
foo n :: Int
n) = 42 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Foo -> Int
unfoo Foo
foo


unnorf :: Norf -> [Foo]
unnorf :: Norf -> [Foo]
unnorf (Norf (Bar, xs :: [Foo]
xs, Bar)) = [Foo]
xs
unnorf (Norf (Baz, xs :: [Foo]
xs, Baz)) = [Foo] -> [Foo]
forall a. [a] -> [a]
reverse [Foo]
xs
unnorf _ = [Foo]
forall a. HasCallStack => a
undefined


unnorf' :: Norf -> Int
unnorf' :: Norf -> Int
unnorf' x :: Norf
x@(Norf (f1 :: Foo
f1@(Quux _ n :: Int
n), _, f2 :: Foo
f2@(Quux f3 :: Foo
f3 _))) =
    Int
x' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Foo -> Int
unfoo Foo
f1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Foo -> Int
aux Foo
f3
  where
    aux :: Foo -> Int
aux fx :: Foo
fx = Foo -> Int
unfoo Foo
f2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Foo -> Int
unfoo Foo
fx Int -> Int -> Int
forall a. Num a => a -> a -> a
* Foo -> Int
unfoo Foo
f3
    x' :: Int
x' = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> (Norf -> [Int]) -> Norf -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Foo -> Int) -> [Foo] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Foo -> Int
unfoo ([Foo] -> [Int]) -> (Norf -> [Foo]) -> Norf -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Norf -> [Foo]
unnorf (Norf -> Int) -> Norf -> Int
forall a b. (a -> b) -> a -> b
$ Norf
x