3 ms·
For those of us who don't do haskell, can you give us an example of what does not work and then work around?
by teruakohatu 7y ago
For those of us who don't do haskell, can you give us an example of what does not work and then work around?
- dwohnitmok 7y agoFor an example of clashing: data Person = Person { id :: Int, name :: Text } data Account = Account { id :: Int, # Oh no! Name clash amount :: Int } This is because `id` isn't really a "field," among other thing it's a generated function so that id :: Amount -> Int id (Amount actualId _) = actualId This particular case is compounded by the fact that `id` is already the name of the identity function in Haskell's standard library (one reason why many projects that roll their own standard library rename `id` to `identity`). For the partiality: data AllowedItems = Person { id :: Int, name :: Text} | JustANormalInteger Int name (JustANormalInteger 5) # Blows up at runtime That is name has the type AllowedItems -> Text, even though JustANormalInteger 5 is also a member of AllowedItems The workaround for clashing is to prefix your fields with your type name (luckily Haskell still has module namespaces so you don't need a globally unique name, just one unique for your module). The workaround for partiality is to disallow a type with a record to be anything other than that record (e.g. disallow JustANormalInteger or require that Person {...} must first be an independent type before it can be used in AllowedItems). The talk of lenses is a way to generalize the notion of field accessors and talk about the "path" generated by a series of field accessors in a first class way. E.g. you might imagine that in a standard OO language myClass.field0.subField0.subSubField0 could have a stand-alone concept of `field0.subField0.subsubField0` as a path through `myClass` that you could then use either to get a value (get(field0.subField0.subSubField0, myClass)) or set a value (set(field0.subField0.subSubField0, myClass, newValue)). Moreover, if you can talk about the paths through a class in a first-class way, what's to say that this path must actually correspond to a true field in a class? It could just be anything "field-like." For example: lens = integer.lastDigit.leastSignificantBit set(345, lens, 0) // Yields 344 even though the individual digits of myInteger aren't actually generally truly fields in any OO language nor are the individual bits of a number. Because you have now removed the need for true "fields," lenses are one strategy to get around the hackiness of fields in Haskell and in fact in many ways represent an advance in expressiveness over "true" fields (although they suffer from not really being integrated into the language in the way faux-fields are currently in Haskell).
- dwohnitmok 7y agoWhoops... apparently I was reading bash while writing this comment. Comments in Haskell should be `--` not `#`.