5 ms·
getValue kind of defeats the purpose of using Maybe in the first place.
by Peaker 13y ago
getValue kind of defeats the purpose of using Maybe in the first place.
- qznc 13y agoUsing getValue corresponds to extracting the value via pattern matching in Haskell. foo (Just a) = bar a For sure, Haskell has better syntax for this. ;)
- Peaker 13y agoIf you have: foo (Just a) = bar a It is typically followed, on the next line by: foo Nothing = ... And if it isn't, and you use -Wall (you really should!) you will get a warning for writing a partial function (which is sometimes warranted, but is a smell). The function "fromJust" which is equivalent to "getValue" is very rarely useful, and considered a smell: making that one of the primary ways to use your Maybe value is a very bad idea. if (isNothing (m)) { .. } else { .. m.getValue() .. } Is much less safe than: case m of Nothing -> { .. } Just val -> .. val .. And has no useful advantage...
- eli_gottlieb 13y agoActually, I use Option.get a lot in Scala code. It's very useful for saying, "I expect this Option[A] to be Some[A] every time the code reaches this point due to a proof I cannot (yet) convey to the type-checker, and if it's not, throw an exception for God's sake!"
- Peaker 13y agoIf you use it a lot it's likely a bad sign. Either that you are not using the type system's power to its full extent, or that the type system is too weak. In Haskell, use of fromJust is considered a code smell, and is of course sometimes justified. But pretty rarely.
- eli_gottlieb 13y agoGenerally, I use it where I could duplicate an entire data type with additional knowledge of the possible types. So for example, "AST that has been type-specialized and therefore contains no polymorphic type variables" would be a different type from "raw AST" or "type-generalized AST". I actually did write the code that way the first time around. However, it ended up being a huge duplication of effort for a tiny amount of increased safety from type-checking. Literally, if I'm willing to move the checks of certain type-system-checkable properties to runtime this way, I can write 1/3 the actual lines of code. The ideal would be to have data structures that are polymorphic over proofs of their properties, allowing the type-system to consider "unchecked AST", "generalized AST" and "specialized AST" as the instantiation of the same basic "AST" data type over three different proofs (or lack of proofs).
- Peaker 13y agoAnother alternative is sharing the types of the various ASTs but using parameterization to distinguish the cases. To restore nice, concise types, use a bunch of type synonyms. While this is slightly cumbersome, I much prefer it over partiality. Ideally, even this wouldn't be necessary, with structural records and variants that let you work with changing, precise types without having to declare a lot of duplicate types.
- eli_gottlieb 13y agoWell that's the issue: I want to distinguish otherwise-identical trees in which certain particular node cases are either allowed or disallowed. In Haskell, AFAIK, that's hard. In Scala, it just requires copying your code over and over again, but it's possible and you can even share some of the code. The other solution I'm thinking of in Scala (that doesn't involve Option[T].get, I mean) is to treat the properties I want "proven" as a set of methods over the data, built as a separate object or trait similar to how Scala represents type-class dictionaries. I can then write one data-structure that quantifies over the type of the proof-witness dictionary it stores as part of itself. So when, for example, I want a fully-instantiated AST with no remaining "holes" to be filled in by static checking, I could write a function that only works on AST[FullyInstantiated]. Functions that don't care about the proof-witness are quantified over it. It then takes a bunch of extra typing to construct the proof-witness instances, but when I'm doing that construction I will have the compiler statically checking that all types relied on by the witness are correct.