Apr 13 2009
Stupid Haskell Tricks
Let’s say that you really, really want some notion of objected oriented programming. So let’s make a class that represents a name, and some simple method calls on it:
data S = S { name :: String } deriving (Show)
firstname s = (words (name s))!!0
lastname s = (words (name s))!!1
But, dammit, you want to invoke it like you would in C++. So define a function:
*Main> let (-->) x f = f x *Main> let test = S "George Washington" *Main> test --> firstname "George" *Main> test --> lastname "Washington"
(It’s tempting to use `.`, but it conflicts with the Prelude. Also note that you could define it as “(–>) = flip ($)”). But what if it takes more than one parameter?
*Main> let flip_concat t s = intercalate t $ reverse.words $ name s
*Main> test --> flip_concat ", "
"Washington, George"
*Main> test --> flip_concat(", ")
"Washington, George"
… although you might not like that anything can be applied to (–>).
*Main> [1,2,3] --> length
3
class Deref a where
(-->) :: a -> (a -> b) -> b
x --> f = f x
instance Deref S
*Main> [1,2,3] --> length
<interactive>:1:0:
No instance for (Deref [t])
arising from a use of `-->' at <interactive>:1:0-17
Possible fix: add an instance declaration for (Deref [t])
In the expression: [1, 2, 3] --> length
In the definition of `it': it = [1, 2, 3] --> length
You can even use tuple passing to make it look even more like a typical call.
*Main> let pretty (pre, mid, post) s = pre ++ (firstname s) ++ mid ++ (lastname s) ++ post
*Main> test --> pretty ("<", ", ", ">")
"<George, Washington>"
… although that makes it harder to curry.