Hi all,
Having worked on The Expression Problem - Part 1 (download for proper image quality), I am now starting out on Part 2, and I am asking myself if it is possible to translate the following Haskell solution of the Expression Problem into Scala 3.
module Main where
import Lib
data Const = Const Int
data Add l r = Add l r
class Expr x
instance Expr Const
instance (Expr l, Expr r) => Expr (Add l r)
class Expr x => Evaluate x
where evaluate :: x -> Int
instance Evaluate Const
where evaluate (Const i) = i
instance (Evaluate l, Evaluate r) => Evaluate (Add l r)
where evaluate (Add l r) = evaluate l + evaluate r
------------------------------------------------------------
-- Add a new expression type without modifying existing code
data Neg x = Neg x
instance Expr x => Expr (Neg x)
instance Evaluate x => Evaluate (Neg x)
where evaluate (Neg x) = 0 - evaluate x
------------------------------------------------------------
-- Add a new function without modifying existing code
class Expr x => Stringify x
where toString :: x -> String
instance Stringify Const
where toString (Const i) = show i
instance (Stringify l, Stringify r) => Stringify (Add l r)
where toString (Add l r) = "(" ++ (toString l) ++ "+" ++ (toString r) ++ ")"
instance Stringify x => Stringify (Neg x)
where toString (Neg x) = "-" ++ (toString x)
-------------------------------------------------------
-- Try it out
four = Const 4
twoPlusThree = Add (Const 2) (Const 3)
twoPlusThreeNegated = Neg (Add (Const 2) (Const 3))
main :: IO ()
main = do
putStrLn (show (evaluate four))
putStrLn (show (evaluate twoPlusThree))
putStrLn (show (evaluate twoPlusThreeNegated))
putStrLn (show (toString four))
putStrLn (show (toString twoPlusThree))
putStrLn (show (toString twoPlusThreeNegated))
A quick way of running this code is to simply paste it in https://replit.com/languages/haskell and click ‘Run’.
Here is the output:
$ main
4
5
-5
"4"
"(2+3)"
"-(2+3)"
As soon as I begin, I get stuck:
case class Const(c: Int)
case class Add[A](l: A, r: A)
trait Expr[A] { }
given Expr[Const] with { }
given expr[A](using l: Expr[A], r: Expr[A]): Expr[Add[Expr[A]]] with { }
Simple scala typeclasses were sufficient to translate the code seen in the above deck, but I reckon I need to learn a great deal in order to attempt this.
Can anyone help?
What Scala 3 features are necessary to pull this off?
I would be grateful for any form of help: pointers to relevant language features/papers/videos, suggestions, examples, code snippets.
Thank you in advance for your help,
Philip