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

adam vogt vogt.adam at gmail.com
Mon Jan 13 06:52:03 UTC 2014


Hi Cary,

Have you looked at
http://www.haskell.org/haskellwiki/Extensible_record and
https://ghc.haskell.org/trac/ghc/wiki/Records ? The named-fields stuff
in haskell 2010 is bad because none of the proposals/implementations
really stand out as the right choice.

You still have a choice whether you want to use newtypes to help you
keep things straight. Maybe your `newtype Mapper` could help you catch
some bugs. Or maybe it just makes some busywork for you, where you
just add some noise (`fn` and `Mapper`) whenever the types don't match
up.

Also consider that the type of "map" doesn't have to be changed to
catch mistakes of using the wrong function: if the concrete types that
end up replacing the `a` and `b` in your actual program are not all
String, the typechecker may still be able to point out a place where
you've been inconsistent (say by using the wrong function).

--
Adam

On Sun, Jan 12, 2014 at 8:00 PM, Cary Cherng <ccherng at gmail.com> wrote:
> 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?
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list