Zainab Ali
@_zainabali_
val people : Map[String, Person] = ...
val peopleAndMe : Map[String, Person] = people.put(
"Zainab" -> Person(...)
)
...
// but I know I exist
val me : Option[Person] = peopleAndMe.get("Zainab")// unsafe code
val me : Person = peopleAndMe("Zainab")data MyDataType : Type where
MyConstructor : (myLabel : String) -> MyDataType
myFunction : MyDataType -> String
myFunction (MyConstructor a) = a
myNumber : Nat
myNumber = 2data Vect : Nat -> Type -> Type where
Nil : Vect 0 a
(::) : a -> Vect n a -> Vect (n + 1) a
dogsILike : Vect 2 String
dogsILike = "Schnauzer" :: "Beagle" :: Nil
dogsIHate : Vect 0 String
dogsIHate = Nil
-- Type error!
cats : Vect 1 String
cats = Nilcase class Account(balance: Int, opCount: Int)
def create(initialBalance: Int):
BalanceShouldBePositive Either Account = ...
def credit(amount: Int, account: Account):
AmountShouldBePositive Either Account = ...
def debit(amount: Int, account: Account):
AmountShouldBePositive Either Account = ...
def transfer(amount: Int,
from: Account,
to: Account):
AmountShouldBePositive Either (Account, Account) = ...val right = create(100)
// has type AmountShouldBePositive Either Account
val left = create(0)
// has type AmountShouldBePositive Either Accountdata Account : Type where
MkAccount : (balance : Nat) -> (opCount : Nat) -> Account
create : Nat ->
Either BalanceShouldBePositive Account
create initialBalance = ...
credit : Nat ->
Account ->
Either AmountShouldBePositive Account
credit amount account = ...
debit : Nat ->
Account ->
Either AmountShouldBePositive Account
debit amount account = ...transfer : Nat ->
Account ->
Account ->
Either AmountShouldBePositive (Account, Account)
transfer amount from to = ...create : (a: Nat) ->
(prf : a `GT` 0) ->
Account
create initialBalance _ = ...-- Type error!
create 0 ?whatProof
amount : Nat
amount = ...
case (isGT 0 amount) of
Yes prf => create amount prf
No _ => ...libraryDependencies += "eu.timepit" %% "refined" % theVersionimport eu.timepit.refined._
import eu.timepit.refined.api.Refined
import eu.timepit.refined.auto._
import eu.timepit.refined.numeric._def create(initialBalance: Int Refined Positive):
Account = ...// Yay!
val account: Account = create(100)// Fails!
val account: Account = create(-5)val amount : Int = ...
val refinedPositive : String Either (Int Refined Positive) =
refineV[Positive](amount)
refinedPositive.map { positiveAmount =>
create(positiveAmount)
}data Account : Type where
MkAccount : (balance : Nat) ->
(opCount : Nat) -> Accountdata Account : (opCount : Nat) -> Type where
MkAccount : (balance : Nat) ->
(opCount : Nat) ->
Account opCountfiveOps : Account 5
fiveOps = MkAccount 10 5create : (a : Nat) ->
(prf : a `GT` 0) ->
Account 0
create initialBalance _ = ...-- Type error!
create : (a : Nat) ->
(prf : a `GT` 0) ->
Account 0
create initialBalance _ = MkAccount initialBalance 3credit : (a : Nat) ->
Account n ->
(prf : a `GT` 0) ->
Account (n + 1)
credit amount account _ = ...5.typecase class Account[OpCount <: Int with Singleton](
balance : Int
)case class Account(balance : Int, opCount: Int)scalaOrganization := "org.typelevel"
scalacOptions += "-Yliteral-types"
val fiveOps : Account[5] = Account[5](3)def create(amount: Int Refined Positive): Account[0] = ...def credit[N <: Int with Singleton](
amount: Int Refined Positive,
account: Account[N]
) : ??? = ...trait IncCount[A <: Account[_]] {
type Out <: Account[_]
def apply(account: A): Out
}
object IncCount {
type Aux[A <: Account[_], Out0 <: Account[_]] =
IncCount[A] {
type Out = Out0
}
}implicit val incCount: IncCount.Aux[Account[0], Account[1]] =
new IncCount[Account[0]] {
type Out = Account[1]
def apply(a: Account[0]): Out = Account[1](a.balance)
}def credit[N <: Int with Singleton](
amount: Int Refined Positive,
account: Account[N])(
implicit incCount: IncCount[Account[N]]
): incCount.Out = ...libraryDependencies += "eu.timepit" %% "singleton-ops" % theVersionimport singleton.ops._object IncCount {
implicit def incCount[N <: Int with Singleton,
IncN <: Int with Singleton](
implicit op: OpInt.Aux[N + 1, IncN]
): Aux[Account[N], Account[IncN]] =
new IncCount[A] {
type Out = Account[IncN]
def apply(account: A): Account[IntN] =
Account(account.balance)
}
}data Account : (opCount : Nat) -> Type where
MkAccount : (balance : Nat) ->
(opCount : Nat) ->
Account opCountdata Account : (opCount : Nat) ->
(balance : Nat) -> Type where
MkAccount : (balance : Nat) ->
(opCount : Nat) ->
Account opCount balancecreate : (a : Nat) ->
(prf : a `GT` 0) ->
Account 0 a
create initialBalance _ = ...
credit : (a : Nat) ->
Account n balance ->
(prf : a `GT` 0) ->
Account (n + 1) (balance + a)
credit amount account _ = ...-- Type error!
debit : (a : Nat) ->
Account n balance ->
(prf : a `GT` 0) ->
Account (n + 1) (balance - a)
debit amount account _ = ...debit : (a : Nat) ->
Account n balance ->
(prf : a `GT` 0) ->
(prf1 : a `LTE` balance) ->
Account (n + 1) (balance - a)
debit amount account _ _ = ...transfer : (a : Nat) ->
Account n nBalance ->
Account m mBalance ->
(prf : a `GT` 0) ->
(prf1 : a `LTE` nBalance) ->
(Account (n + 1) (balance - a),
Account (m + 1) (balance + a))
transfer amount from to _ _ = ...