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 Int
0


unfoo :: Foo -> Int
unfoo :: Foo -> Int
unfoo Foo
Bar = Int
0
unfoo Foo
Baz = Int
0
unfoo (Quux Foo
foo Int
n) = Int
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 (Foo
Bar, [Foo]
xs, Foo
Bar)) = [Foo]
xs
unnorf (Norf (Foo
Baz, [Foo]
xs, Foo
Baz)) = [Foo] -> [Foo]
forall a. [a] -> [a]
reverse [Foo]
xs
unnorf Norf
_ = [Foo]
forall a. HasCallStack => a
undefined


unnorf' :: Norf -> Int
unnorf' :: Norf -> Int
unnorf' x :: Norf
x@(Norf (f1 :: Foo
f1@(Quux Foo
_ Int
n), [Foo]
_, f2 :: Foo
f2@(Quux Foo
f3 Int
_))) =
    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 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