[Haskell-cafe] Structural typing of records in Haskell?

Cary Cherng ccherng at gmail.com
Mon Jan 13 01:00:23 UTC 2014

Are there statically typed languages that treat records with
structural typing, either imperative or functional?

Why should records not be structurally typed in Haskell? From what I
understand, in the below foo cannot take a Rec2 even though Rec1 and
Rec2 are essentially the same.

data Rec1 = Rec1 { a :: Int, b :: Bool}
data Rec2 = Rec2 { a :: Int, b :: Bool}
foo :: Rec1 -> Bool

Rec1 and Rec2 could be in totally different code libraries. I've read
that preventing Rec2 being used in foo is good for the type safety in
that Rec1 and Rec2 are likely intended to have semantically different
meanings and allowing interchangeability breaks this.

But then why is map structurally typed. map takes an argument of type
a -> b and suppose some other higher order function bar also takes an
argument of type a -> b. Should map instead have the below type which
prevents a function of type a -> b semantically intended for bar from
being accidentally used in map.

newtype Mapper a b = Mapper { fn :: a -> b }
map :: Mapper a b -> [a] -> [b]
map _ [] = []
map f (x:xs) = (fn f) x : map f xs

If there is a mechanism that prevents something of type Rec2 from
accidentally being used in foo, then why shouldn't there be something
analogous that prevents something of type a -> b (meant for bar) from
accidentally being used in map?

More information about the Haskell-Cafe mailing list