July 23rd, 2024

Types as Interfaces

The article explores using wrapper types like Msg and Timestamped in Haskell to annotate data without modifying existing types directly. It discusses challenges in composing annotated types and suggests using typeclasses for solutions. Emphasizes simplifying code for essential variants.

Read original articleLink Icon
Types as Interfaces

The article discusses the concept of using types as interfaces in Haskell programming. It explores creating wrapper types to add extra fields to existing types without modifying them directly. By introducing wrapper types like Msg and Timestamped, the article demonstrates how to annotate data with additional information while maintaining composability. It also delves into the challenges of composing different annotated types and proposes the use of typeclasses to address such issues. The author suggests drawing inspiration from layered network protocols to design code with meaningful structure. The article concludes by emphasizing the importance of simplifying code by focusing on essential variants and adapting to meet the primary requirements. Overall, it provides insights into leveraging type systems to design flexible and structured code in Haskell programming.

Related

Interface Upgrades in Go (2014)

Interface Upgrades in Go (2014)

The article delves into Go's interface upgrades, showcasing their role in encapsulation and decoupling. It emphasizes optimizing performance through wider interface casting, with examples from io and net/http libraries. It warns about complexities and advises cautious usage.

A reckless introduction to Hindley-Milner type inference (2019)

A reckless introduction to Hindley-Milner type inference (2019)

Hindley-Milner type inference balances expressiveness and legibility in programming languages like Elm and Haskell. It enhances correctness by enforcing strict type checking, limiting coding practices for improved type safety.

Ergonomic Self-Referential Types for Rust

Ergonomic Self-Referential Types for Rust

Yoshua Wuyts introduces Ergonomic Self-Referential Types for Rust, enhancing self-referential types accessibility. Features include self lifetimes, fixed memory locations, immovable types, and safe self-references initialization. The discussion showcases async {} and Future usage, emphasizing tracking references and potential Rust type system enhancements. Collaboration with Eric Holk is acknowledged for exploring !Move implications.

Evolving Languages Faster with Type Tailoring

Evolving Languages Faster with Type Tailoring

Programming languages face limitations in understanding domain-specific aspects like regular expressions, causing errors. "Type Tailoring" proposes teaching type systems new tricks through metaprogramming tools for improved code efficiency and correctness.

Parse, Don't Validate

Parse, Don't Validate

The article explores type-driven design in programming, emphasizing "Parse, don’t validate" in Haskell. It showcases using types for robust code, avoiding errors, and enhancing input parsing efficiency in various tasks.

Link Icon 17 comments
By @user3939382 - 4 months
I’ve come to believe that a type should be capable of reflecting any arbitrary rules a programmer knows about the bounds of a value. The only real implementations of this I see are mostly academic with a dependent type system like Idris. We’re many years from that becoming mainstream, if it ever will be.
By @auggierose - 4 months
Indeed, TypeScript can do exactly this and more, without much ceremony:

    type FooBar = Foo & Bar
I doubt you will find a language where it is less clunky.

Edit: Oh, I typed this on mobile, this was supposed to be a comment on another comment by posix_monad.

By @posix_monad - 4 months
MLs require a lot of ceremony modelling simple record types.

What we want to express here is an object with a map of properties (name to type):

    string Type map
For the OOP minded:

    Map<string, Type>
And also compose those:

    type Foo = { "_foo", int }

    type Bar = { "_bar", string }

    type FooBar = mergeMaps Foo Bar
But at compile-time, of course.

Have any languages achieved this? I know TypeScript can do some of these things, but it's clunky.

By @brabel - 4 months
Is this something professional programmers are having trouble with??

This is the kind of problem you face in your first year working, no? I am honetly curious what others think. Do you have trouble deciding when to use an interface (assuming your language has that), or a type wrapper (I don't think that's the brightest idea), or a function to extract the field to sort by (most languages do that)??

By @pierrebai - 4 months
Some of the ideas in the blog must be speculative, given that it fell through a wormhole, being published September 17, 2024.
By @jolux - 4 months
published…2024-09-17?
By @fungiblecog - 4 months
Rich Hickey would say "just use maps" and avoid all this navel-gazing
By @spankalee - 4 months
This is a lot of complication for in what most OOP languages with interfaces would simply be something like:

    interface Timestamped {
      timestamp: UTCTime;
    }
    interface Msg {
      sender: PlayerId;
    }
    class Quote implements Timestamped, Msg {
      timestamp: UTCTime;
      sender: PlayerId;
    }
Why is this so hard in Haskell? It doesn't have interface polymorphism?
By @sickblastoise - 4 months
I would love to just throw a field Optional[Datetime.UTC] on Msg type and call it a day :). Cool article got me thinking at 6:00 AM
By @LudwigNagasena - 4 months
> People say that types-as-interfaces are not composable

Who says that and what does it even suppose to mean?

By @fellowniusmonk - 4 months
Primitive types and schemas.

Complex types and objects don't exist.

Embrace Mereological Nihilism.

It's fun at meetups to tell everyone your programming paradigm is Nihilism.

By @indulona - 4 months
problem of known types, or interfaces, as values is that conditions for the value format or validation changes based on context. so you might have a price that is valid in one context but not in another(like a negative value). the problem then occurs on the input where you might let in value that is valid on higher level but not on deeper level and by the time you detect it it might be too late(you have committed a transaction with invalid data).
By @tinix - 4 months
types are not interfaces.

interfaces describe behavior, types describe shape and structure. the difference is subtle but important.

By @dingosity - 4 months
meh. or you could use mixins.
By @Xen9 - 4 months
Differences in foundational understanding & unteachability of foundational research causes inevitably ton of confusion in texts on formal science ideas outside a known academic context.

This text should not fascinate a programmer but create frustration of two types: (1) Frustration on one's lack of small pieces knowledge (2) Frustration that NOW you will not have the chance to invent this on your ow; your creative process takes damage.

Out of which the second type should be the one that makes majority of cases.

ALSO this should cause one to have respect of form: "hey, this programmer was probably at least smart enough to figure out this alone."

Perhaps most polite woule be to, for every text, in the situation to have notice at beginning: "For programmers who already have thought about what would happen were you to add X to Y but so that Z enough to probably not to get new ideas in this context."