Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save missingfaktor/e0c236ff03f70739be812a5058f220d5 to your computer and use it in GitHub Desktop.
Save missingfaktor/e0c236ff03f70739be812a5058f220d5 to your computer and use it in GitHub Desktop.

In Haskell, if you want to create a hierarchy of types (and there will be needs at times), you use an encoding like below:

data CustomerCreatedAction = CustomerCreatedAction { ...stuff... }

data JourneyRunnerAction = JourneyRunnerAction { ...stuff... }

data Action = AC CustomerCreatedAction
            | AJ JourneyRunnerAction

You could do the same in Scala.

But you could also make use of the fact that data constructors also yield their own types in Scala, like shown below:

sealed trait Action
final case class CustomerCreatedAction(...stuff...) extends Action
final case class JourneyRunnerAction(...stuff...) extends Action

Let's say in your program, you start from a point where you know the thing is an Action but not of which kind. You use pattern matching to narrow down to the exact kind of action. In the Haskell approach shown above, the way you pass down the evidence of this narrowed down view is by unwrapping the data. In the Scala approach, the evidence is implied by the subtyping relationship.

doCustomeryThings :: CustomerCreatedAction -> Int
doCustomeryThings = ...stuff...

doJourneyeyThings :: JourneyRunnerAction -> Int
doJourneyeyThings = ...stuff...

act :: Action
act = ...stuff...

case act of 
  AC customerCreatedAction -> doCustomeryThings customerCreatedAction
  AJ journeyRunnerAction   -> doJourneyeyThings journeyRunnerAction

def doCustomeryThings(action: CustomerCreatedAction): Int = ...stuff...
def doJourneyeyThings(action: JourneyRunnerAction): Int = ...stuff...

val action: Action = ...stuff...

action match {
  case c: CustomerCreatedAction => doCustomeryThings(c)
  case j: JourneyRunnerAction   => doJourneyeyThings(j)
}

Can you give examples of cases where the approach used in Haskell code above gives advanatages over the one used in Scala code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment