Skip to content

Instantly share code, notes, and snippets.

@phadej
Created August 6, 2014 10:38
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 phadej/bdc67048df66a574df5a to your computer and use it in GitHub Desktop.
Save phadej/bdc67048df66a574df5a to your computer and use it in GitHub Desktop.
The Scala translation of this particular Agda code snippet is quite close to the C++ version. Exercise: translate to Haskell.
module Ref where
open import Prelude
-- We have three mutually circular types, "entities": Foksi, Fusku and Fuksi
-- (Note: Finnish is an awesome language: Foksi, Fusku and Fuksi are foxtrot, single-time swing and freshman respectively)
-- Each entity value has an identifier.
Identifier : Set
Identifier = Nat
-- The problem is that in a database entities might have circular dependencies
-- foo is related to bar is related to foo etc.
-- So we have "natural number" like reference type
-- zero reference is only an ID
-- successor references are actual values
record Reference : Set where
constructor mkReference
field
refid : Identifier
Ref : (Nat → Set) → Nat → Set
Ref E zero = Reference
Ref E (suc n) = E n
-- And the actual data
record Foksi (n : Nat) : Set
record Fusku (n : Nat) : Set
record Fuksi (n : Nat) : Set
record Foksi n where
constructor mkFoksi
field
ident : Identifier
fun : Bool
fusku : Ref Fusku n
record Fusku n where
constructor mkFusku
field
ident : Identifier
slow : Bool
fuksi : Ref Fuksi n
record Fuksi n where
constructor mkFuksi
field
ident : Identifier
lost : Bool
foksi : List (Ref Foksi n)
module Demo where
-- Foksi 0 is "shallow" version
foksiShallow : Foksi 0
foksiShallow = record { ident = 0 ; fun = true ; fusku = mkReference 1 }
-- Foksi 3 is "deeper" but not infinitely deep though
foksiDeeper : Foksi 3
foksiDeeper = mkFoksi 0 true
(mkFusku 1 false
(mkFuksi 2 true
(mkFoksi 0 true (mkReference 1) ∷
mkFoksi 3 true (mkReference 1) ∷ [])))
-- Problem:
-- Encode this in Scala.
-- Inception:
postulate Context : Set
record Entity (E : Nat → Set) : Set where
field
deeper : Context → {n : Nat} → E n → E (suc n) -- unfold one level of reference
-- We could serialize Foksi to human readable string, if it's deep enough:
render : ∀ {n} → Foksi (suc n) → String
render (mkFoksi ident fun (mkFusku ident₁ slow fuksi)) = "Foksi " & show ident & " is like fusku " & show ident₁
-- Compilles
example : render Demo.foksiDeeper ≡ "Foksi 0 is like fusku 1"
example = refl
-- Doesn't compile
{-
zero != (suc _n_37) of type Nat
when checking that the expression Demo.foksiShallow has type
Foksi (suc _n_37)
-}
-- example2 : String
-- example2 = render Demo.foksiShallow
package Ref
import language.higherKinds
package object TypeAliases {
type ID = Long
}
import TypeAliases._
sealed trait Entity {
val id : ID
}
final case class Reference (
id : ID
) extends Entity
sealed trait RefIdx {
type ref[E[_ <: RefIdx] <: Entity] <: Entity
}
sealed trait RZero extends RefIdx {
type ref[E[_ <: RefIdx] <: Entity] = Reference
}
sealed trait RSucc[N <: RefIdx] extends RefIdx {
type ref[E[_ <: RefIdx] <: Entity] = E[N]
}
final case class Foksi[N <: RefIdx] (
id: ID,
fun: Boolean,
fusku: N#ref[Fusku]
) extends Entity
final case class Fusku[N <: RefIdx] (
id: ID,
slow: Boolean,
fuksi: N#ref[Fuksi]
) extends Entity
final case class Fuksi[N <: RefIdx] (
id: ID,
lost: Boolean,
foksi: List[N#ref[Foksi]]
) extends Entity
package object Demo {
type ROne = RSucc[RZero]
type RTwo = RSucc[ROne]
type RThree = RSucc[RTwo]
val foksiShallow : Foksi[RZero] = Foksi[RZero](0, true, Reference(1))
val foksiDeep : Foksi[RThree] = Foksi[RThree](0, true,
Fusku[RTwo](1, false,
Fuksi[ROne](2, true, List(
Foksi[RZero](0, true, Reference(1)),
Foksi[RZero](3, true, Reference(1))))))
}
#include <vector>
typedef long ID;
struct Entity {
ID id;
Entity(ID id) : id(id) {}
};
struct Reference : public Entity {
Reference(ID id) : Entity(id) {}
};
template<unsigned long N, template<unsigned long M> class E> struct RefIdx {
typedef E<N-1> ref;
};
template<template<unsigned long M> class E>
struct RefIdx<0, E> {
typedef Reference ref;
};
template<unsigned long N> struct Foksi;
template<unsigned long N> struct Fusku;
template<unsigned long N> struct Fuksi;
template<unsigned long N> struct Foksi : public Entity {
bool fun;
typename RefIdx<N, Fusku>::ref fusku;
Foksi(ID id, bool fun, typename RefIdx<N, Fusku>::ref fusku) : Entity(id), fun(fun), fusku(fusku) {}
};
template<unsigned long N> struct Fusku : public Entity {
bool slow;
typename RefIdx<N, Fuksi>::ref fuksi;
Fusku(ID id, bool slow, typename RefIdx<N, Fuksi>::ref fuksi) : Entity(id), slow(slow), fuksi(fuksi) {}
};
template<unsigned long N> struct Fuksi : public Entity {
bool lost;
std::vector<typename RefIdx<N, Foksi>::ref> foksi;
public:
Fuksi(ID id, bool lost, std::vector<typename RefIdx<N, Foksi>::ref> foksi) : Entity(id), lost(lost), foksi(foksi) {}
};
int main() {
const Foksi<0> shallowFoksi(0, true, Reference(1));
std::vector<Foksi<0>> foksi = { Foksi<0>(0, true, Reference(1)),
Foksi<0>(3, true, Reference(1)) };
const Foksi<3> deepFoksi(0, true,
Fusku<2>(1, false,
Fuksi<1>(2, true, foksi)));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment