All Projects → pkamenarsky → Knit

pkamenarsky / Knit

Licence: bsd-3-clause
Ties the knot on data structures that reference each other by unique keys

Programming Languages

haskell
3896 projects

Projects that are alternatives of or similar to Knit

Data Structures In Open Source
Data structures used in open source projects around the world.
Stars: ✭ 9 (-80%)
Mutual labels:  data-structures
Algos And Data Structures
Collection of Test Specs and Implementation of various algorithms and data structures from the Princeton Coursera course: Intro to Algorithms part 1 and 2
Stars: ✭ 31 (-31.11%)
Mutual labels:  data-structures
Algo Phantoms Backend
💻 Algo-Phantoms-Backend is an Application that provides pathways and quizzes along with a code editor to help you towards your DSA journey.📰🔥 This repository contains the REST APIs of the application.✨
Stars: ✭ 36 (-20%)
Mutual labels:  data-structures
Huprog
A repo which includes the HUPROG'17(Hacettepe University Programming Contest)'s questions and the solutions of that questions.
Stars: ✭ 11 (-75.56%)
Mutual labels:  data-structures
Xinblog
前端基础。Vue框架。数据结构与算法。计算机网络。夯实基础。
Stars: ✭ 29 (-35.56%)
Mutual labels:  data-structures
Algorithms
Study cases for Algorithms and Data Structures.
Stars: ✭ 32 (-28.89%)
Mutual labels:  data-structures
Ods
Mission: To provide a high-quality open content data structures textbook that is both mathematically rigorous and provides complete implementations.
Stars: ✭ 932 (+1971.11%)
Mutual labels:  data-structures
Libgenerics
libgenerics is a minimalistic and generic library for C basic data structures.
Stars: ✭ 42 (-6.67%)
Mutual labels:  data-structures
Fundamentals Of Python Data Structures
《数据结构(Python语言描述)》"Fundamentals of Python:Data Structures" 电子书和配套代码
Stars: ✭ 30 (-33.33%)
Mutual labels:  data-structures
Lib9wada
Wonderful library with lots of useful functions, algorithms and data structures in C, link it with -l9wada
Stars: ✭ 35 (-22.22%)
Mutual labels:  data-structures
Lintcode
📜 Lintcode/Leetcode algorithm written by Java, Python and JavaScript.
Stars: ✭ 21 (-53.33%)
Mutual labels:  data-structures
Ds Algo Point
This repository contains codes for various data structures and algorithms in C, C++, Java, Python, C#, Go, JavaScript, PHP, Kotlin and Scala
Stars: ✭ 949 (+2008.89%)
Mutual labels:  data-structures
O
Ring-buffers in go without interface{}
Stars: ✭ 33 (-26.67%)
Mutual labels:  data-structures
Python Programming
Python Coding - Data Structure, Algorithm, Crypto, Web, Network, System
Stars: ✭ 9 (-80%)
Mutual labels:  data-structures
Learn some algorithm and data structure
从零开始回顾一下最简单最基础的算法与数据结构
Stars: ✭ 38 (-15.56%)
Mutual labels:  data-structures
Competitive Programming Library
A library designed to improve your competitive programming performance.
Stars: ✭ 26 (-42.22%)
Mutual labels:  data-structures
Algos
Popular Algorithms and Data Structures implemented in popular languages
Stars: ✭ 966 (+2046.67%)
Mutual labels:  data-structures
Algorithms
Solved algorithms and data structures problems in many languages
Stars: ✭ 1,021 (+2168.89%)
Mutual labels:  data-structures
Algorithms
🍣 Implementations of fundamental algorithms and data structures. Happy Hacktoberfest!
Stars: ✭ 41 (-8.89%)
Mutual labels:  data-structures
Algorithm study
algorithms and data structures for coding contest (designed for 'copy & paste')
Stars: ✭ 33 (-26.67%)
Mutual labels:  data-structures

knit

CircleCI

knit ties the knot on data structures that reference each other by unique keys. Above all it aims to be easy to use - boilerplate is kept to a minimum and its API is as simple as it gets.

Example

data Person model m = Person
  { name        :: Id model m String
  , loves       :: ForeignId model m "persons" "name" --
  , isPresident :: Bool                               --
  } deriving (Generic, KnitRecord Model)              --
                                                      -- 
data Model m = Model                                  --
  { persons :: Table Model m Person -- <----------------
  } deriving (Generic, KnitTables)

Let's break that down: when defining a domain type, like Person, we'll need two additional type parameters that will determine the final shape of that type: the model Person belongs to (it may belong to multiple models), and its "mode" (m) - whether it's resolved or unresolved. Additionally, we need to derive KnitRecord for every domain type, supplying it with a concrete model type.

Id model m t will define a key this type is referenced by (multiple keys are possible).

ForeignId is where the magic happens - in addition to the two generic parameters from above it takes a "table" name (which is just a field in the model) and a field name in the referenced domain type; the final type of the ForeignId field (both resolved and unresolved) can then be inferred from this information alone!

To define a model, wrap each domain type with a Table and autoderive the KnitTables typeclass.

Let's take a look:

alice :: Person Model 'Unresolved
alice = Person
  { name        = Id "Alice"
  , loves       = ForeignId "Bob"  -- this must be a String, since Model.persons.name is a String!
  , isPresident = False
  }

bob :: Person Model 'Unresolved
bob = Person
  { name        = Id "Bob"
  , loves       = ForeignId "Alice"
  , isPresident = False
  }

model :: Model 'Unresolved
model = Model
  { persons = [alice, bob]  -- `Table` is just a regular list
  }

So far so good. Resolving an unresolved model is just a matter of calling knit:

knitModel :: Model Resolved
knitModel = case knit model of
  Right resolved -> resolved
  Left e -> error (show e)

(knit may fail due to invalid or duplicate keys). If all goes well, we'll get the following resolved model, if we were to do it by hand:

manualAlice :: Person Model 'Resolved
manualAlice = Person
  { name        = "Alice"
  , loves       = Lazy manualBob
  , isPresident = False
  }

manualBob :: Person Model 'Resolved
manualBob = Person
  { name        = "Bob"
  , loves       = Lazy manualAlice
  , isPresident = False
  }

manualModel :: Model 'Resolved
manualModel = Model
  { persons = [manualAlice, manualBob]
  }

Lazy is just a simple wrapper with a get field:

data Lazy a = { get :: a }

And here it is, a nicely knit model:

name $ get $ loves (persons knitModel !! 0) -- "Bob"

The test directory contains more examples, with multiple domain types.

Cascading deletes

By supplying a Remove key instead the regular Id a record is marked for deletion:

alice :: Person Model 'Unresolved
alice = Person
  { name        = Remove "Alice"  -- mark the record for deletion
  , loves       = ForeignId "Bob"
  , isPresident = False
  }

This will remove the record from the resolved result, as well as all other records that depend transitively on it. Invalid keys (i.e. ForeignIds that reference non-existent Ids) will still throw an error when knit-ting a model.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].