{-# LANGUAGE Haskell2010 #-}
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 forall a. Num a => a -> a -> a
* Int
n 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)) = forall a. [a] -> [a]
reverse [Foo]
xs
unnorf Norf
_ = 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' forall a. Num a => a -> a -> a
+ Int
n forall a. Num a => a -> a -> a
* Foo -> Int
unfoo Foo
f1 forall a. Num a => a -> a -> a
+ Foo -> Int
aux Foo
f3
  where
    aux :: Foo -> Int
aux Foo
fx = Foo -> Int
unfoo Foo
f2 forall a. Num a => a -> a -> a
* Foo -> Int
unfoo Foo
fx forall a. Num a => a -> a -> a
* Foo -> Int
unfoo Foo
f3
    x' :: Int
x' = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map Foo -> Int
unfoo forall b c a. (b -> c) -> (a -> b) -> a -> c
. Norf -> [Foo]
unnorf forall a b. (a -> b) -> a -> b
$ Norf
x