Created
August 6, 2014 10:38
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)))))) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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