top | item 40797536

(no title)

philh | 1 year ago

I'm not familiar with that technique and don't know what's going on from that snippet.

In Haskell, any time a heterogeneous list turns out to be fine, I expect to be able to model it. Often it'll look like "I'm applying a polymorphic function to every one of these list elements", and then you can either do a sum type (as discussed in the post) or an existential (which doesn't need you to list up front all the types you might use). If the function is "is negative?", it'll look something like (untested)

    data SomeNum = forall a. Num a => SomeNum a

    isNegative :: SomeNum -> Bool
    isNegative (SomeNum n) = n < 0

    numbers = [SomeNum (3 :: Int), SomeNum (5.2 :: Double), SomeNum valOfUnexpectedNumericType]
    anyNegative = any isNegative numbers
...but it'll often be easier to just apply the `< 0` check to every element before putting them in the list. (If you have several functions you want to apply to them all, that's when the existential trick becomes more useful.)

So you can model heterogeneous lists in this case, and it's safer (because you can't put in a value that can't be compared to 0) but also less convenient. Whether that's an improvement or not will depend on the situation.

discuss

order

trealira|1 year ago

I also just learned about it. I found this explanation of what it is: https://drup.github.io/2016/08/02/difflists/

It's a slightly confusing name, though; it makes me think of a difference list, which seems to be a completely unrelated data structure (basically a rope).

http://h2.jaguarpaw.co.uk/posts/demystifying-dlist/

philh|1 year ago

Thanks. Yeah, I don't understand the name.

You could construct a basically-equivalent data structure in Haskell, but I think normally you'd use an HList (defined in many places but e.g. https://hackage.haskell.org/package/HList-0.5.2.0/docs/Data-...). I've only occasionally had use for them myself, at any rate I don't think they're convenient for the "apply a function to all these elements" case.

yawaramin|1 year ago

In the technique I showed, I am using a difflist to enumerate a set of HTTP POST form fields and their expected types. This difflist type is defined in such a way that one of its type parameters gets inferred as a function type which takes the decoded values in the correct order and returns a record containing the decoded form. Eg from Field.[int "id"; string "name"] we get a type parameter int -> string -> 'a, where 'a is the type of the final decoded form.

This is the kind of real-world usage where difflists or heterogeneous lists shine. The same technique is used by this library to define type-safe GraphQL resolvers: https://github.com/andreas/ocaml-graphql-server