3 ms·
Regarding your second point, what would be the functional equivalent?
by thisjepisje 12y ago
Regarding your second point, what would be the functional equivalent?
- GeneralMayhem 12y agoInfix notation in Haskell is close, except that most of the time if verb syntax is convenient you're expecting side-effects.
- Ixiaus 12y agoHe means pattern matching functions, which are idiomatic in Erlang but "dirty" in Haskell (where you would want to solve it better with a type class, or something else more general). Erlang myfun({duck, "My Duck's Name"}) -> dosomething; myfun({dog, "My Dog's Name"}) -> dosomething; myfun({cat, "My Cat's Name"}) -> dosomething. Erlang also has arity matching (this function is different than the one above it): myfun({cat, "My Cat's Name"}, cage) -> dosomething. Case statements are one way of doing that but those are considered a messy style in Erlang because they end up nesting so deeply - keeping it all out in small little functions and using pattern and arity matching is the "right" way. You can do the same (except for arity matching) in Haskell with function arg pattern matching and Haskell also has some very nice projection tools for it too: Haskell newtype Name = Name { unwrapName :: String } data Animal = Cat | Dog | Duck deriving (Eq, Show, Ord) myfun :: Maybe Animal -> Name -> String myfun (Just a) (unwrapName -> name) = (show a) ++ "'s name is: " ++ name myfun Nothing _ = "No animal given!" > let n = Name "Fido" > myfun (Maybe Cat) n > "Cat's name is: Fido" > > myfun Nothing n > "No animal given!" There are many problems with that function and I could probably eliminate the multiple function clauses and reduce it to one clause by getting rid of the pattern matching and using the maybe function: myfun :: Maybe Animal -> Name -> String myfun a (unwrapName -> n) = maybe default formatAnimal a where default = "No animal given!" formatAnimal t = printf "%s's name is: %s" (show t) n That would be the more idiomatic way I would do it - pattern matching isn't "bad" in Haskell and you'll see it used quite often in utilities and libraries. It's considered good form to move stuff like that into a utility and give it a clear name (like the maybe function above that takes our formatAnimal function) then use that in your application code so it becomes obvious what's going on. Pattern matching, deeply nested ifs and cases, etc... are somewhat hard to parse for the eye.
- thisjepisje 12y agoJust getting into Erlang right now, this is very helpful.
- codygman 12y agoWhat is concept is the: newtype Name = Name { unwrapName :: String } (unwrapName -> name) I'm not familiar with this, are you pattern matching on a function type?
- dezgeg 12y agoIt's the View Patterns extension: https://ghc.haskell.org/trac/ghc/wiki/ViewPatterns https://ghc.haskell.org/trac/ghc/wiki/ViewPatterns
- l_dopa 12y agoYou would pass in a function or datatype containing a function, which is exactly what the OO code does. No language features beyond first class functions necessary.
- captainmuon 12y agoI was thinking of something like in F# (disclaimer: I've never used it and copied this from MSDN): type Shape = | Rectangle of height : float * width : float | Circle of radius : float let matchShape shape = match shape with | Rectangle(height = h) -> printfn "Rectangle with length %f" h | Circle(r) -> printfn "Circle with radius %f" r Admittedly, this is not too far from a simple `if`, but I believe the language ensures that you handle all cases. The difference to OOP is that the code is in one place, with the function, instead of distributed, with all objects. It makes it easier to add functions, but harder to add new types. Often, this is the better option, but if you are writing truely extensible code (a library that gets passed custom objects, or an application with add-ins) then you want to go the OOP way.