Created
March 27, 2020 20:31
-
-
Save louthy/17a9f3d0747db1b9ceb6028231838479 to your computer and use it in GitHub Desktop.
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
using Echo; | |
using LanguageExt; | |
using static LanguageExt.Prelude; | |
using static Echo.Process; | |
using System; | |
namespace StackOverflow2 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var s1 = Student.New("Joe Bloggs", 24); | |
var s2 = Student.New("John Doe", 22); | |
var s3 = Student.New("Jane Doe", 21); | |
var t1 = Teacher.New("Richard Smith", 56); | |
var t2 = Teacher.New("Paul Louth", 44); | |
ProcessConfig.initialise(); | |
var db = spawn<Database, DatabaseMsg>("db", DatabaseActor.Setup, DatabaseActor.Inbox); | |
tell(db, AddStudent.New(s1)); | |
tell(db, AddStudent.New(s2)); | |
tell(db, AddStudent.New(s3)); | |
tell(db, AddTeacher.New(t1)); | |
tell(db, AddTeacher.New(t2)); | |
tell(db, AssignStudentToTeacher.New(s1, t1)); | |
tell(db, AssignStudentToTeacher.New(s2, t1)); | |
tell(db, AssignStudentToTeacher.New(s3, t2)); | |
ask<Set<Teacher>>(db, FindStudentTeachers.New(s1)).Iter(Console.WriteLine); | |
ask<Set<Teacher>>(db, FindStudentTeachers.New(s2)).Iter(Console.WriteLine); | |
ask<Set<Teacher>>(db, FindStudentTeachers.New(s3)).Iter(Console.WriteLine); | |
ask<Set<Student>>(db, FindTeacherStudents.New(t1)).Iter(Console.WriteLine); | |
ask<Set<Student>>(db, FindTeacherStudents.New(t2)).Iter(Console.WriteLine); | |
tell(db, RemoveTeacher.New(t2)); | |
ask<Set<Student>>(db, FindGhostStudents.New()).Iter(Console.WriteLine); | |
tell(db, RemoveStudent.New(s1)); | |
ask<Set<Student>>(db, FindTeacherStudents.New(t1)).Iter(Console.WriteLine); | |
tell(db, RemoveStudent.New(s2)); | |
ask<Set<Student>>(db, FindTeacherStudents.New(t1)).Iter(Console.WriteLine); | |
} | |
} | |
[Record] | |
public partial class Student | |
{ | |
public readonly string Name; | |
public readonly int Age; | |
} | |
[Record] | |
public partial class Teacher | |
{ | |
public readonly string Name; | |
public readonly int Age; | |
} | |
[Record] | |
public partial class Database | |
{ | |
public static readonly Database Empty = new Database(default, default, default, default); | |
public readonly Map<Teacher, Set<Student>> TeacherStudents; | |
public readonly Map<Student, Set<Teacher>> StudentTeachers; | |
public readonly Set<Student> Students; | |
public readonly Set<Teacher> Teachers; | |
public Database AddTeacher(Teacher teacher) => | |
With(Teachers: Teachers.Add(teacher), | |
TeacherStudents: TeacherStudents.Add(teacher, default)); | |
public Database AddStudent(Student student) => | |
With(Students: Students.Add(student), | |
StudentTeachers: StudentTeachers.Add(student, default)); | |
public Database AssignStudentToTeacher(Student student, Teacher teacher) => | |
With(StudentTeachers: StudentTeachers.SetItem(student, Some: ts => ts.AddOrUpdate(teacher)), | |
TeacherStudents: TeacherStudents.SetItem(teacher, Some: ss => ss.AddOrUpdate(student))); | |
public Database UnAssignStudentFromTeacher(Student student, Teacher teacher) => | |
With(StudentTeachers: StudentTeachers.SetItem(student, Some: ts => ts.Remove(teacher)), | |
TeacherStudents: TeacherStudents.SetItem(teacher, Some: ss => ss.Remove(student))); | |
public Database RemoveTeacher(Teacher teacher) => | |
With(Teachers: Teachers.Remove(teacher), | |
TeacherStudents: TeacherStudents.Remove(teacher), | |
StudentTeachers: StudentTeachers.Map(ts => ts.Remove(teacher))); | |
public Database RemoveStudent(Student student) => | |
With(Students: Students.Remove(student), | |
StudentTeachers: StudentTeachers.Remove(student), | |
TeacherStudents: TeacherStudents.Map(ss => ss.Remove(student))); | |
public Option<Teacher> FindTeacher(string name, int age) => | |
Teachers.Find(new Teacher(name, age)); | |
public Option<Student> FindStudent(string name, int age) => | |
Students.Find(new Student(name, age)); | |
public Set<Student> FindTeacherStudents(Teacher teacher) => | |
TeacherStudents | |
.Find(teacher) | |
.IfNone(Set<Student>()); | |
public Set<Teacher> FindStudentTeachers(Student student) => | |
StudentTeachers | |
.Find(student) | |
.IfNone(Set<Teacher>()); | |
public Set<Student> FindGhostStudents() => | |
toSet(StudentTeachers.Filter(teachers => teachers.IsEmpty).Keys); | |
} | |
[Union] | |
public interface DatabaseMsg | |
{ | |
DatabaseMsg AddTeacher(Teacher teacher); | |
DatabaseMsg AddStudent(Student student); | |
DatabaseMsg AssignStudentToTeacher(Student student, Teacher teacher); | |
DatabaseMsg UnAssignStudentFromTeacher(Student student, Teacher teacher); | |
DatabaseMsg RemoveTeacher(Teacher teacher); | |
DatabaseMsg RemoveStudent(Student student); | |
DatabaseMsg FindTeacher(string name, int age); | |
DatabaseMsg FindStudent(string name, int age); | |
DatabaseMsg FindTeacherStudents(Teacher teacher); | |
DatabaseMsg FindStudentTeachers(Student student); | |
DatabaseMsg FindGhostStudents(); | |
} | |
public static class DatabaseActor | |
{ | |
public static Database Setup() => | |
Database.Empty; | |
public static Database Inbox(Database state, DatabaseMsg msg) => | |
msg switch | |
{ | |
AddTeacher (var teacher) => state.AddTeacher(teacher), | |
AddStudent (var student) => state.AddStudent(student), | |
AssignStudentToTeacher (var student, var teacher) => state.AssignStudentToTeacher(student, teacher), | |
UnAssignStudentFromTeacher (var student, var teacher) => state.UnAssignStudentFromTeacher(student, teacher), | |
RemoveTeacher (var teacher) => state.RemoveTeacher(teacher), | |
RemoveStudent (var student) => state.RemoveStudent(student), | |
FindTeacher (var name, var age) => constant(state, reply(state.FindTeacher(name, age))), | |
FindStudent (var name, var age) => constant(state, reply(state.FindStudent(name, age))), | |
FindTeacherStudents (var teacher) => constant(state, reply(state.FindTeacherStudents(teacher))), | |
FindStudentTeachers (var student) => constant(state, reply(state.FindStudentTeachers(student))), | |
FindGhostStudents _ => constant(state, reply(state.FindGhostStudents())), | |
_ => state | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment