haskell like type classes in scala
2010-06-21 comments | scala, haskell, programmingwe all surely know how type classes in haskell work and how to use them. ;)
maybe a bit like this:
class (Show a) => MyTypeClass a where
absFunc :: a -> String
concFunc :: a -> String
concFunc a = "concrete(" ++ show a ++ ")"
data FooBar = FooBar { foo :: String, bar :: String } deriving (Show)
printIt :: (MyTypeClass a) => a -> String
printIt a = absFunc a ++ " " ++ concFunc a
instance MyTypeClass FooBar where
absFunc (FooBar f b) = "foo(" ++ show f ++ "), bar(" ++ show b ++ ")"
main::IO()
main = putStrLn $ printIt $ FooBar "hallo" "welt"
this example generates an output like this:
> runhaskell typeClass.hs
foo("hallo"), bar("welt") concrete(FooBar {foo = "hallo", bar = "welt"})
with scala it is also possible to define and use type classes using implicits.
here's a simple example which has the advantage over haskell, that the type instances only apply to the surrounding scope, where the haskell type instances are global. (please correct me if I'm wrong)
trait MyTypeClass[T] {
def absFunc(a: T): String
def concFunc(a: T): String = "concrete(%s)".format(a)
}
def printIt[T: MyTypeClass](t: T) = implicitly[MyTypeClass[T]].absFunc(t) + " " +
implicitly[MyTypeClass[T]].concFunc(t)
class FooBar(val foo: String, val bar: String)
object MyInstance {
implicit object FooBarTypeClass extends MyTypeClass[FooBar] {
def absFunc(a: FooBar): String = {
import a._
"foo(%s), bar(%s)".format(foo, bar)
}
}
}
val fb1 = new FooBar("hallo", "welt")
{ import MyInstance._
println(printIt(fb1))
}
object MySpecialInstance {
implicit object FooBarSpecialTypeClass extends MyTypeClass[FooBar] {
def absFunc(a: FooBar): String = {
import a._
"FOO => %s, BAR => %s".format(foo, bar)
}
override def concFunc(a: FooBar): String = {
import a._
"concrete(%s, %s)".format(foo, bar)
}
}
}
{ import MySpecialInstance._
println(printIt(fb1))
}
the output should look like this:
> scala typeClasses.scala
foo(hallo), bar(welt) concrete(Main$$anon$1$FooBar@fcfa52)
FOO => hallo, BAR => welt concrete(hallo, welt)
please note, that scala 2.8 is needed.
hth