Necessity/utility of dependent types?

how could you possibly validate or invalidate something which doesn't exist yet? That logic cannot possibly disappear at runtime.

Supposing you write validEmail "foo@bar" :: Maybe Email, you now have to handle a case which will never happen, despite knowing as a programmer right now that this is correct. Dependent types can let you run your validation function at compile-time on the string [email protected]. Thus the logic disappeared at runtime.

Simplifying with a type like:

data NameChar = F | O
data DomainChar = B | A | R | M U
data NonEmpty = Cons a [a]
data Email = Email (NonEmpty NameChar) (NoneEmpty DomainChar)

That's a grammar for a very limited set of emails.

Then I can construct Email (Cons F (Cons O (Cons O))) (Cons B (Cons A (Cons R))) for "foo@bar" and know that it is a valid construction based on the constraints set in NameChar and DomainChar. I can also provide a validEmail :: String -> Maybe Email type for runtime construction. But I had the option to have a compile-time construct too.

Where dependent types come in in this example is that I can't, in regular Haskell, go from a string literal [Char] to the Email type without introducing partiality, because there isn't enough type information in Char to use type functions, and I don't have the ability to run code at compile time (without template-haskell). A dependent type system would let me define something like parseEmail :: (str :: [Char]) -> toType (fromStr str) where toType returns the type () if the string is invalid, and returns the type Email if valid, so that parseEmail "foo@bar" :: Email whereas parseEmail "" :: ().

See printf in Idris for a more compelling example.

/r/haskell Thread Parent