Syntactic Cheat Sheet
Translating from TypeScript to Haskell

Basics

Comments

TypeScript
Haskell
1
// This is a TypeScript comment
2
3
/*
4
Need more space?
5
No problem!
6
This is a multi-line TypeScript comment :)
7
*/
8
9
/**
10
* In TS, you write documentation like this for TypeDoc
11
*/
12
const id = a => a
Copied!
1
-- This is a Haskell comment
2
3
{-
4
Need more space?
5
No problem!
6
This is a multi-line Haskell comment :)
7
-}
8
9
--| Add a pipe for a short function description
10
-- You can keep talking about is afterwards
11
-- These will turn into formatted documentation with Haddock
12
id a = a
13
14
{-| You can use a multi-line comment for Haddock, too
15
The same rules apply.
16
-}
17
swap (a, b) -> (b, a)
Copied!

Assignment

Implicit Type

TypeScript
Haskell
1
const hi = "Hello World"
Copied!
1
hi = "Hello World"
Copied!

Explicit Type

TypeScript
Haskell
Haskell (Local Clarification Variant)
1
const hi: string = 'Hello World'
Copied!
1
hi :: Text
2
hi = "Hello World"
Copied!
1
hi = ("Hello World" :: Text)
Copied!

Functions

Anonymous

TypeScript
Haskell
Haskell (Shorthand)
1
a => a * 2
Copied!
1
\a -> a * 2
2
-- NOTE: `\` is an easier to type lambda `λ`
Copied!
1
(*2)
Copied!

Named

TypeScript
Haskell
Haskell (Shorthand)
1
const double = (a : number) => a * 2
Copied!
1
double :: Int -> Int
2
double a = a * 2
Copied!
1
double :: Int -> Int
2
double = (*2)
Copied!

Infix

TypeScript
Haskell
1
// Does not exist
Copied!
1
(*&) :: Int -> String -> String
2
num *& str = show num ++ str
3
-- NOTE: `show` turns values into strings
Copied!

Argument Application

TypeScript
Haskell
1
const result = doTheThing(1, 2, ["a", "b"], 1.1)
Copied!
1
result = doTheThing 1 2 ["a", "b"] 1.1
Copied!

Side-Effectful

TypeScript
Haskell
1
fireTheMissiles()
Copied!
1
fireTheMissiles
Copied!

Inner Scope

TypeScript
Haskell (let...in)
Haskell (where)
1
const withInner = (toLog: string): void => {
2
const innerValue = 'That is the question!'
3
console.log(`${toLog}? Or not ${toLog}? ${innerValue}`)
4
}
Copied!
1
withInner' toLog =
2
let
3
innerValue = "That is the question!"
4
msg = toLog <> "? Or not " <> toLog <> "? " <> innerValue
5
in
6
logInfo msg
Copied!
1
withInner toLog = logInfo msg
2
where
3
msg = toLog <> "? Or not " <> toLog <> "? " <> innerValue
4
innerValue = "That is the question!"
Copied!

Nested Application

TypeScript
Haskell (parens)
Haskell (applied with $)
Haskell (Piped with &)
1
const result = triple(prod(1, double(1), 3))
2
3
/* i.e.
4
const two = double(1)
5
const six = prod(1, two, 3)
6
const result = triple(six)
7
*/
Copied!
1
result = triple (prod 1 (double 1) 3)
Copied!
1
result = triple $ prod 1 (double 1) 3
Copied!
1
result = 3
2
& prod 1 (double 1)
3
& triple
Copied!

Composition

TypeScript
Haskell
1
const timesSix = (a: number): number => triple(double(a))
Copied!
1
timesSix :: Int -> Int
2
timeSix = triple . double
Copied!

Partial Application

TypeScript
Haskell
Haskell (Point-Free Style)
1
const math = (n: number, m: number): number =
2
triple(prod(10, double(1), n), m)
Copied!
1
math :: Int -> Int -> Int
2
math n m = triple (prod 10 (double 1) n) m
Copied!
1
math :: Int -> Int -> Int
2
math = triple . prod 10 (double 1)
Copied!

Modules

TypeScript
Haskell
1
import * from "./GetEverything"
2
import * as HL from "./HelperLib";
3
import { foo, bar } from "./SomeLib"
4
5
const id = a => a
6
const swap = ([a, b]) => [b, a]
7
const hiddenValue = HL.downcase("not exported")
8
9
export {
10
id,
11
swap
12
}
13
14
export { toReExport } from "./ExternalLib"
Copied!
1
module MyModule
2
( id
3
, swap
4
, toReExport
5
) where
6
7
import GetEverything
8
import SomeLib (foo, bar)
9
import ExternalLib (toReExport)
10
import qualified HelperLib as HL
11
12
id a = a
13
swap (a, b) = (b, a)
14
hiddenValue = HL.downcase "not exported"
Copied!

Types & Data

Type Alias

TypeScript
Haskell
1
type Name = string
2
type Balance = number
Copied!
1
type Name = Text
2
type Balance = Int
Copied!

Sum / Enum / Coproduct

TypeScript
Haskell
1
type TrafficLight = 'RED' | 'YELLOW' | 'GREEN'
Copied!
1
data TrafficLight
2
= Red
3
| Yellow
4
| Green
Copied!

Product

TypeScript
Haskell
1
type GearRatio = [number, number] // [big gear, little gear]
2
type Bike = [string, GearRatio] // [bikeName, gear ratio]
Copied!
1
data GearRatio = GearRatio Int Int
2
data Bike = Bike Text GearRatio
Copied!

Interfaces & Classes → Records

TypeScript (Interface)
TypeScript (Class)
Haskell
1
interface GearRatio {
2
big: number
3
little: number
4
}
5
6
interface Bike {
7
name: string
8
gear: GearRatio
9
}
Copied!
1
class Geared {
2
big: number
3
little: number
4
5
constructor(gbr: number, lgr: number) {
6
big = bgr
7
little = lgr
8
}
9
}
10
11
class Bike extends Geared {
12
name: string
13
14
constructor(bgr: number, lgr: number, bikeName: string) {
15
name = bikeName
16
super(bgr, lgr)
17
}
18
}
Copied!
1
data Gear = GearRatio
2
{ _big :: Natural
3
, _little :: Natural
4
}
5
6
data Bike = Bike
7
{ _name :: Text
8
, _gear :: Gear
9
}
Copied!

Constructors

TypeScript (Direct)
TypeScript (Class)
Haskell
1
const makeGear = (big, little): GearRatio => ({ big, little })
2
3
const makeBike = (big, little, name): Bike => ({
4
name,
5
gear = makeGear(big, little)
6
})
Copied!
1
/*
2
Included in the `class` delcaration. For example:
3
4
constructor(bgr: number, lgr: number) {
5
big = bgr
6
little = lgr
7
}
8
*/
Copied!
1
{-
2
Constructors are the capitalized word on
3
the right of the `=` in the `data` declaration
4
It auto-generates constructor functions
5
with the folling type signatures:
6
7
GearRatio :: Natural -> Natural -> Geared
8
Bike :: Text -> GearRatio -> Bike
9
-}
Copied!

Instantiation

TypeScript (Direct)
TypeScript (Class)
Haskell
Haskell (Record Style)
Haskell (Wildcard Style)
1
const myBike = makeBike(2, 5, '10 Speeder')
Copied!
1
const myBike = new Bike(2, 5, '10 Speeder')
Copied!
1
myBike = Bike "10 Speeder" (GearRatio 2 5)
Copied!
1
myBike = Bike
2
{ _name = "10 Speeder" -- Use named fields
3
, _gear = GearRatio 2 5 -- Or just ordered values
4
}
Copied!
1
myBike :: Bike
2
myBike =
3
let
4
_big = 2
5
_little = 5
6
_name = "10 Speeder"
7
_gear = GearRatio {..}
8
in
9
Bike {..}
Copied!

Getters

TypeScript (Dot Syntax)
TypeScript (Destructuring)
Haskell (Destructuring)
Haskell (Wildcard Style)
Haskell (Lenses)
1
const big: number = myGears.big
2
const little = myBike.gear.little
Copied!
1
const { bigGear } = myGears
2
const getBig = ({ big }) => big
3
const ratio = ({ big, little }) => big / little
Copied!
1
GearRatio big _ = myGears
2
getBig (GearRatio {_big}) = _big
3
ratio (GearRatio {_big, _little}) = _big / _little
Copied!
1
ratio (GearRatio {..}) = _big / _little
Copied!
1
import Control.Lens.TH
2
3
$(makeLenses ''Gear)
4
$(makeLenses ''Bike)
5
6
myGear ^. big -- NOTE: lenses have no underscores!
7
8
-- Nested
9
10
myBike ^. gear . little
Copied!

Updating with Setters

TypeScript
Haskell (Record Syntax)
Haskell (Lenses)
1
// Preamble
2
3
const myGear = new GearRatio(2, 5)
4
const myBike = new Bike('10 Speeder', myGear)
5
6
// Mutable Update
7
8
myGear.littleGear = 6
9
myBike.name = '12 Speeder'
10
11
// Immutable Update
12
13
const upgradedGear = Object.assign({}, myGear)
14
const upgradedBike = Object.assign({}, myBike, {gear: upgradedGear})
Copied!
1
-- Preamble
2
3
myGear = GearRatio 2 5
4
myBike = Bike "10 Speeder" myGear
5
6
-- Immutable Update
7
8
upgradedBike = myBike
9
{ _name = "12 Speeder"
10
, _gear = myGear { _littleGear = 6 }
11
}
Copied!
1
-- Preamble
2
3
import Control.Lens.TH
4
5
makeLenses ''Gear
6
makeLenses ''Bike
7
8
myGear = GearRatio 2 5
9
myBike = Bike "10 Speeder" myGear
10
11
-- Immutable Update
12
13
upgradedBike = myBike & name .~ "12 Speeder"
14
& gear.littleGear .~ 6
Copied!

Branching

If...Else

TypeScript
TypeScript Ternary
Haskell
1
if (condition) {
2
branchA
3
} else {
4
branchB
5
}
Copied!
1
condition ? branchA : branchB
Copied!
1
if condition
2
then branchA
3
else branchB
Copied!

If...Else If...Else

TypeScript
Haskell
1
if (percent >= 90 || student.paidBribe) {
2
return GRADES.A
3
} else if (percent >= 75) {
4
return GRADES.B
5
} else if (percent >= 60) {
6
return GRADES.C
7
} else if (percent >= 50) {
8
return GRADES.D
9
} else {
10
return GRADES.F
11
}
Copied!
1
if | percent >= 90 || paidBribe student = A
2
| percent >= 75 = B
3
| percent >= 60 = C
4
| percent >= 50 = D
5
| otherwise = F
Copied!

Switch/Case

TypeScript
Haskell
1
let nextAction
2
3
switch (lightState) {
4
case LIGHT.RED:
5
nextAction = ACTION.STOP
6
break
7
8
case LIGHT.YELLOW:
9
nextAction = ACTION.SLOW
10
break
11
12
case LIGHT.GREEN:
13
nextAction = ACTION.DRIVE
14
break
15
16
default:
17
nextAction = currentAction
18
}
Copied!
1
nextAction =
2
case lightState of
3
Red -> Stop
4
Yellow -> Slow
5
Green -> Drive
6
_ -> currentAction
Copied!
Last modified 2yr ago