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 = 2
data 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 = Nil
case 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 Account
data 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" % theVersion
import 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) -> Account
data Account : (opCount : Nat) -> Type where
MkAccount : (balance : Nat) ->
(opCount : Nat) ->
Account opCount
fiveOps : Account 5
fiveOps = MkAccount 10 5
create : (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 3
credit : (a : Nat) ->
Account n ->
(prf : a `GT` 0) ->
Account (n + 1)
credit amount account _ = ...
5.type
case 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" % theVersion
import 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 opCount
data Account : (opCount : Nat) ->
(balance : Nat) -> Type where
MkAccount : (balance : Nat) ->
(opCount : Nat) ->
Account opCount balance
create : (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 _ _ = ...