data Foo = Foo Int Double Bool
-- See? So much clearer and safer and stuff!
“I have a
Foo
… but this function requires aBar
which is identical to aFoo
just with a different name…
In type theory a product type of two types
A
andB
is the type whose terms are ordered pairs(a,b)
witha:A
andb:B
.
GHC.Generics
Everything is either:
K1
– An individual field/constructorV1
– Empty datatypesU1
– A constructor without fields:*:
– Product types:+:
– Sum typesM1
– Pesky, pesky metadata…Generic
M1
wrappers presentM1
wrappers that the other type wantsλ> data Foo a c = Foo a Int c
deriving (Show, Generic)
λ> data Bar b = Bar { a :: Word
, b :: b
, c :: Char
}
deriving (Show, Generic)
λ> transmogrify (Foo (3 :: Word) 2 'a')
:: Bar Int
Bar {a = 3, b = 2, c = 'a'}
… it’s a tad boring.
('t', 'u', 'p', 'l', 'e')
(('t', 'u'), 'p', ('l', 'e'))
('t', ('u', ('p', ('l', ('e')))))
't' :*: ('u' :*: ('p' :*: ('l' :*: ('e'))))
λ> transmogrify
('H', 'a', 's', 'k', 'e', 'l', 'l')
:: ((Char, Char)
, Char
, (Char, Char, (Char, Char)))
(('H','a'),'s',('k','e',('l','l')))
transmogrify :: (SameShape a b) => a -> b
λ> :type transmogrify
transmogrify
:: (Raw' a (CanRecurse a)
~ Raw' b (CanRecurse b)
, RawShape' b (CanRecurse b)
, RawShape' a (CanRecurse a)) =>
a -> b
type family CanRecurse a :: Bool where
CanRecurse Int = 'False
CanRecurse Int8 = 'False
CanRecurse Int16 = 'False
CanRecurse Int32 = 'False
CanRecurse Int64 = 'False
CanRecurse Integer = 'False
-- Snip other numeric types
CanRecurse Char = 'False
CanRecurse a = 'True