diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2022 Gautier DI FOLCO
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/bench/LinkedList/ScenarioDirect.hs b/bench/LinkedList/ScenarioDirect.hs
new file mode 100644
--- /dev/null
+++ b/bench/LinkedList/ScenarioDirect.hs
@@ -0,0 +1,8 @@
+module LinkedList.ScenarioDirect where
+
+import Data.Records.Yarl.LinkedList
+import LinkedList.Type
+
+sumDirect :: LinkedListRecord -> Int
+sumDirect (Field a0 :> Field a1 :> Field a2 :> Field a3 :> Field a4 :> Field a5 :> Field a6 :> Field a7 :> Field a8 :> Field a9 :> Field a10 :> Field a11 :> Field a12 :> Field a13 :> Field a14 :> Field a15 :> Field a16 :> Field a17 :> Field a18 :> Field a19 :> Field a20 :> Field a21 :> Field a22 :> Field a23 :> Field a24 :> Field a25 :> Field a26 :> Field a27 :> Field a28 :> Field a29 :> Field a30 :> Field a31 :> Field a32 :> Field a33 :> Field a34 :> Field a35 :> Field a36 :> Field a37 :> Field a38 :> Field a39 :> Field a40 :> Field a41 :> Field a42 :> Field a43 :> Field a44 :> Field a45 :> Field a46 :> Field a47 :> Field a48 :> Field a49 :> Field a50 :> Field a51 :> Field a52 :> Field a53 :> Field a54 :> Field a55 :> Field a56 :> Field a57 :> Field a58 :> Field a59 :> Field a60 :> Field a61 :> Field a62 :> Field a63 :> RNil) =
+  a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 + a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32 + a33 + a34 + a35 + a36 + a37 + a38 + a39 + a40 + a41 + a42 + a43 + a44 + a45 + a46 + a47 + a48 + a49 + a50 + a51 + a52 + a53 + a54 + a55 + a56 + a57 + a58 + a59 + a60 + a61 + a62 + a63
diff --git a/bench/LinkedList/ScenarioGetValueClass.hs b/bench/LinkedList/ScenarioGetValueClass.hs
new file mode 100644
--- /dev/null
+++ b/bench/LinkedList/ScenarioGetValueClass.hs
@@ -0,0 +1,7 @@
+module LinkedList.ScenarioGetValueClass where
+
+import GHC.Records
+
+sumGetValueClass :: (HasField "a0" r Int, HasField "a1" r Int, HasField "a2" r Int, HasField "a3" r Int, HasField "a4" r Int, HasField "a5" r Int, HasField "a6" r Int, HasField "a7" r Int, HasField "a8" r Int, HasField "a9" r Int, HasField "a10" r Int, HasField "a11" r Int, HasField "a12" r Int, HasField "a13" r Int, HasField "a14" r Int, HasField "a15" r Int, HasField "a16" r Int, HasField "a17" r Int, HasField "a18" r Int, HasField "a19" r Int, HasField "a20" r Int, HasField "a21" r Int, HasField "a22" r Int, HasField "a23" r Int, HasField "a24" r Int, HasField "a25" r Int, HasField "a26" r Int, HasField "a27" r Int, HasField "a28" r Int, HasField "a29" r Int, HasField "a30" r Int, HasField "a31" r Int, HasField "a32" r Int, HasField "a33" r Int, HasField "a34" r Int, HasField "a35" r Int, HasField "a36" r Int, HasField "a37" r Int, HasField "a38" r Int, HasField "a39" r Int, HasField "a40" r Int, HasField "a41" r Int, HasField "a42" r Int, HasField "a43" r Int, HasField "a44" r Int, HasField "a45" r Int, HasField "a46" r Int, HasField "a47" r Int, HasField "a48" r Int, HasField "a49" r Int, HasField "a50" r Int, HasField "a51" r Int, HasField "a52" r Int, HasField "a53" r Int, HasField "a54" r Int, HasField "a55" r Int, HasField "a56" r Int, HasField "a57" r Int, HasField "a58" r Int, HasField "a59" r Int, HasField "a60" r Int, HasField "a61" r Int, HasField "a62" r Int, HasField "a63" r Int) => r -> Int
+sumGetValueClass r =
+  r.a0 + r.a1 + r.a2 + r.a3 + r.a4 + r.a5 + r.a6 + r.a7 + r.a8 + r.a9 + r.a10 + r.a11 + r.a12 + r.a13 + r.a14 + r.a15 + r.a16 + r.a17 + r.a18 + r.a19 + r.a20 + r.a21 + r.a22 + r.a23 + r.a24 + r.a25 + r.a26 + r.a27 + r.a28 + r.a29 + r.a30 + r.a31 + r.a32 + r.a33 + r.a34 + r.a35 + r.a36 + r.a37 + r.a38 + r.a39 + r.a40 + r.a41 + r.a42 + r.a43 + r.a44 + r.a45 + r.a46 + r.a47 + r.a48 + r.a49 + r.a50 + r.a51 + r.a52 + r.a53 + r.a54 + r.a55 + r.a56 + r.a57 + r.a58 + r.a59 + r.a60 + r.a61 + r.a62 + r.a63
diff --git a/bench/LinkedList/ScenarioGetValueConcrete.hs b/bench/LinkedList/ScenarioGetValueConcrete.hs
new file mode 100644
--- /dev/null
+++ b/bench/LinkedList/ScenarioGetValueConcrete.hs
@@ -0,0 +1,8 @@
+module LinkedList.ScenarioGetValueConcrete where
+
+import Data.Records.Yarl.LinkedList
+import LinkedList.Type
+
+sumGetValueConcrete :: LinkedListRecord -> Int
+sumGetValueConcrete r =
+  r.a0 + r.a1 + r.a2 + r.a3 + r.a4 + r.a5 + r.a6 + r.a7 + r.a8 + r.a9 + r.a10 + r.a11 + r.a12 + r.a13 + r.a14 + r.a15 + r.a16 + r.a17 + r.a18 + r.a19 + r.a20 + r.a21 + r.a22 + r.a23 + r.a24 + r.a25 + r.a26 + r.a27 + r.a28 + r.a29 + r.a30 + r.a31 + r.a32 + r.a33 + r.a34 + r.a35 + r.a36 + r.a37 + r.a38 + r.a39 + r.a40 + r.a41 + r.a42 + r.a43 + r.a44 + r.a45 + r.a46 + r.a47 + r.a48 + r.a49 + r.a50 + r.a51 + r.a52 + r.a53 + r.a54 + r.a55 + r.a56 + r.a57 + r.a58 + r.a59 + r.a60 + r.a61 + r.a62 + r.a63
diff --git a/bench/LinkedList/Type.hs b/bench/LinkedList/Type.hs
new file mode 100644
--- /dev/null
+++ b/bench/LinkedList/Type.hs
@@ -0,0 +1,71 @@
+module LinkedList.Type where
+
+import Data.Records.Yarl.LinkedList
+
+type LinkedListRecord =
+  Record
+    [ Field "a0" Int,
+      Field "a1" Int,
+      Field "a2" Int,
+      Field "a3" Int,
+      Field "a4" Int,
+      Field "a5" Int,
+      Field "a6" Int,
+      Field "a7" Int,
+      Field "a8" Int,
+      Field "a9" Int,
+      Field "a10" Int,
+      Field "a11" Int,
+      Field "a12" Int,
+      Field "a13" Int,
+      Field "a14" Int,
+      Field "a15" Int,
+      Field "a16" Int,
+      Field "a17" Int,
+      Field "a18" Int,
+      Field "a19" Int,
+      Field "a20" Int,
+      Field "a21" Int,
+      Field "a22" Int,
+      Field "a23" Int,
+      Field "a24" Int,
+      Field "a25" Int,
+      Field "a26" Int,
+      Field "a27" Int,
+      Field "a28" Int,
+      Field "a29" Int,
+      Field "a30" Int,
+      Field "a31" Int,
+      Field "a32" Int,
+      Field "a33" Int,
+      Field "a34" Int,
+      Field "a35" Int,
+      Field "a36" Int,
+      Field "a37" Int,
+      Field "a38" Int,
+      Field "a39" Int,
+      Field "a40" Int,
+      Field "a41" Int,
+      Field "a42" Int,
+      Field "a43" Int,
+      Field "a44" Int,
+      Field "a45" Int,
+      Field "a46" Int,
+      Field "a47" Int,
+      Field "a48" Int,
+      Field "a49" Int,
+      Field "a50" Int,
+      Field "a51" Int,
+      Field "a52" Int,
+      Field "a53" Int,
+      Field "a54" Int,
+      Field "a55" Int,
+      Field "a56" Int,
+      Field "a57" Int,
+      Field "a58" Int,
+      Field "a59" Int,
+      Field "a60" Int,
+      Field "a61" Int,
+      Field "a62" Int,
+      Field "a63" Int
+    ]
diff --git a/bench/LinkedList/Value.hs b/bench/LinkedList/Value.hs
new file mode 100644
--- /dev/null
+++ b/bench/LinkedList/Value.hs
@@ -0,0 +1,72 @@
+module LinkedList.Value where
+
+import Data.Records.Yarl.LinkedList
+import LinkedList.Type
+
+oneRecord :: LinkedListRecord
+oneRecord =
+  Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> Field 1
+    :> RNil
diff --git a/bench/Main.hs b/bench/Main.hs
new file mode 100644
--- /dev/null
+++ b/bench/Main.hs
@@ -0,0 +1,27 @@
+module Main where
+
+import Control.DeepSeq
+import Criterion.Main
+import qualified LinkedList.ScenarioDirect as LinkedList
+import qualified LinkedList.ScenarioGetValueClass as LinkedList
+import qualified LinkedList.ScenarioGetValueConcrete as LinkedList
+import qualified LinkedList.Value as LinkedList
+import qualified PlainRecord.ScenarioDirect as PlainRecord
+import qualified PlainRecord.ScenarioGetValueClass as PlainRecord
+import qualified PlainRecord.ScenarioGetValueConcrete as PlainRecord
+import qualified PlainRecord.Type as PlainRecord
+import qualified PlainRecord.Value as PlainRecord
+
+main :: IO ()
+main =
+  defaultMain
+    [ bench "PlainRecord.sumDirect" $ nf' PlainRecord.sumDirect PlainRecord.oneRecord,
+      bench "PlainRecord.sumGetValueConcrete" $ nf' PlainRecord.sumGetValueConcrete PlainRecord.oneRecord,
+      bench "PlainRecord.sumGetValueClass" $ nf' PlainRecord.sumGetValueClass PlainRecord.oneRecord,
+      bench "LinkedList.sumDirect" $ nf' LinkedList.sumDirect LinkedList.oneRecord,
+      bench "LinkedList.sumGetValueConcrete" $ nf' LinkedList.sumGetValueConcrete LinkedList.oneRecord,
+      bench "LinkedList.sumGetValueClass" $ nf' LinkedList.sumGetValueClass LinkedList.oneRecord
+    ]
+
+nf' :: (NFData b, Num b) => (a -> b) -> a -> Benchmarkable
+nf' f = nf (sum . map f) . replicate 1000000
diff --git a/bench/PlainRecord/ScenarioDirect.hs b/bench/PlainRecord/ScenarioDirect.hs
new file mode 100644
--- /dev/null
+++ b/bench/PlainRecord/ScenarioDirect.hs
@@ -0,0 +1,7 @@
+module PlainRecord.ScenarioDirect where
+
+import PlainRecord.Type
+
+sumDirect :: Record -> Int
+sumDirect Record {..} =
+  a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 + a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32 + a33 + a34 + a35 + a36 + a37 + a38 + a39 + a40 + a41 + a42 + a43 + a44 + a45 + a46 + a47 + a48 + a49 + a50 + a51 + a52 + a53 + a54 + a55 + a56 + a57 + a58 + a59 + a60 + a61 + a62 + a63
diff --git a/bench/PlainRecord/ScenarioGetValueClass.hs b/bench/PlainRecord/ScenarioGetValueClass.hs
new file mode 100644
--- /dev/null
+++ b/bench/PlainRecord/ScenarioGetValueClass.hs
@@ -0,0 +1,7 @@
+module PlainRecord.ScenarioGetValueClass where
+
+import GHC.Records
+
+sumGetValueClass :: (HasField "a0" r Int, HasField "a1" r Int, HasField "a2" r Int, HasField "a3" r Int, HasField "a4" r Int, HasField "a5" r Int, HasField "a6" r Int, HasField "a7" r Int, HasField "a8" r Int, HasField "a9" r Int, HasField "a10" r Int, HasField "a11" r Int, HasField "a12" r Int, HasField "a13" r Int, HasField "a14" r Int, HasField "a15" r Int, HasField "a16" r Int, HasField "a17" r Int, HasField "a18" r Int, HasField "a19" r Int, HasField "a20" r Int, HasField "a21" r Int, HasField "a22" r Int, HasField "a23" r Int, HasField "a24" r Int, HasField "a25" r Int, HasField "a26" r Int, HasField "a27" r Int, HasField "a28" r Int, HasField "a29" r Int, HasField "a30" r Int, HasField "a31" r Int, HasField "a32" r Int, HasField "a33" r Int, HasField "a34" r Int, HasField "a35" r Int, HasField "a36" r Int, HasField "a37" r Int, HasField "a38" r Int, HasField "a39" r Int, HasField "a40" r Int, HasField "a41" r Int, HasField "a42" r Int, HasField "a43" r Int, HasField "a44" r Int, HasField "a45" r Int, HasField "a46" r Int, HasField "a47" r Int, HasField "a48" r Int, HasField "a49" r Int, HasField "a50" r Int, HasField "a51" r Int, HasField "a52" r Int, HasField "a53" r Int, HasField "a54" r Int, HasField "a55" r Int, HasField "a56" r Int, HasField "a57" r Int, HasField "a58" r Int, HasField "a59" r Int, HasField "a60" r Int, HasField "a61" r Int, HasField "a62" r Int, HasField "a63" r Int) => r -> Int
+sumGetValueClass r =
+  r.a0 + r.a1 + r.a2 + r.a3 + r.a4 + r.a5 + r.a6 + r.a7 + r.a8 + r.a9 + r.a10 + r.a11 + r.a12 + r.a13 + r.a14 + r.a15 + r.a16 + r.a17 + r.a18 + r.a19 + r.a20 + r.a21 + r.a22 + r.a23 + r.a24 + r.a25 + r.a26 + r.a27 + r.a28 + r.a29 + r.a30 + r.a31 + r.a32 + r.a33 + r.a34 + r.a35 + r.a36 + r.a37 + r.a38 + r.a39 + r.a40 + r.a41 + r.a42 + r.a43 + r.a44 + r.a45 + r.a46 + r.a47 + r.a48 + r.a49 + r.a50 + r.a51 + r.a52 + r.a53 + r.a54 + r.a55 + r.a56 + r.a57 + r.a58 + r.a59 + r.a60 + r.a61 + r.a62 + r.a63
diff --git a/bench/PlainRecord/ScenarioGetValueConcrete.hs b/bench/PlainRecord/ScenarioGetValueConcrete.hs
new file mode 100644
--- /dev/null
+++ b/bench/PlainRecord/ScenarioGetValueConcrete.hs
@@ -0,0 +1,7 @@
+module PlainRecord.ScenarioGetValueConcrete where
+
+import PlainRecord.Type
+
+sumGetValueConcrete :: Record -> Int
+sumGetValueConcrete r =
+  r.a0 + r.a1 + r.a2 + r.a3 + r.a4 + r.a5 + r.a6 + r.a7 + r.a8 + r.a9 + r.a10 + r.a11 + r.a12 + r.a13 + r.a14 + r.a15 + r.a16 + r.a17 + r.a18 + r.a19 + r.a20 + r.a21 + r.a22 + r.a23 + r.a24 + r.a25 + r.a26 + r.a27 + r.a28 + r.a29 + r.a30 + r.a31 + r.a32 + r.a33 + r.a34 + r.a35 + r.a36 + r.a37 + r.a38 + r.a39 + r.a40 + r.a41 + r.a42 + r.a43 + r.a44 + r.a45 + r.a46 + r.a47 + r.a48 + r.a49 + r.a50 + r.a51 + r.a52 + r.a53 + r.a54 + r.a55 + r.a56 + r.a57 + r.a58 + r.a59 + r.a60 + r.a61 + r.a62 + r.a63
diff --git a/bench/PlainRecord/Type.hs b/bench/PlainRecord/Type.hs
new file mode 100644
--- /dev/null
+++ b/bench/PlainRecord/Type.hs
@@ -0,0 +1,68 @@
+module PlainRecord.Type where
+
+data Record = Record
+  { a0 :: Int,
+    a1 :: Int,
+    a2 :: Int,
+    a3 :: Int,
+    a4 :: Int,
+    a5 :: Int,
+    a6 :: Int,
+    a7 :: Int,
+    a8 :: Int,
+    a9 :: Int,
+    a10 :: Int,
+    a11 :: Int,
+    a12 :: Int,
+    a13 :: Int,
+    a14 :: Int,
+    a15 :: Int,
+    a16 :: Int,
+    a17 :: Int,
+    a18 :: Int,
+    a19 :: Int,
+    a20 :: Int,
+    a21 :: Int,
+    a22 :: Int,
+    a23 :: Int,
+    a24 :: Int,
+    a25 :: Int,
+    a26 :: Int,
+    a27 :: Int,
+    a28 :: Int,
+    a29 :: Int,
+    a30 :: Int,
+    a31 :: Int,
+    a32 :: Int,
+    a33 :: Int,
+    a34 :: Int,
+    a35 :: Int,
+    a36 :: Int,
+    a37 :: Int,
+    a38 :: Int,
+    a39 :: Int,
+    a40 :: Int,
+    a41 :: Int,
+    a42 :: Int,
+    a43 :: Int,
+    a44 :: Int,
+    a45 :: Int,
+    a46 :: Int,
+    a47 :: Int,
+    a48 :: Int,
+    a49 :: Int,
+    a50 :: Int,
+    a51 :: Int,
+    a52 :: Int,
+    a53 :: Int,
+    a54 :: Int,
+    a55 :: Int,
+    a56 :: Int,
+    a57 :: Int,
+    a58 :: Int,
+    a59 :: Int,
+    a60 :: Int,
+    a61 :: Int,
+    a62 :: Int,
+    a63 :: Int
+  }
diff --git a/bench/PlainRecord/Value.hs b/bench/PlainRecord/Value.hs
new file mode 100644
--- /dev/null
+++ b/bench/PlainRecord/Value.hs
@@ -0,0 +1,72 @@
+module PlainRecord.Value where
+
+import PlainRecord.Type
+
+oneRecord :: Record
+oneRecord =
+  Record
+    { a0 = 1,
+      a1 = 1,
+      a2 = 1,
+      a3 = 1,
+      a4 = 1,
+      a5 = 1,
+      a6 = 1,
+      a7 = 1,
+      a8 = 1,
+      a9 = 1,
+      a10 = 1,
+      a11 = 1,
+      a12 = 1,
+      a13 = 1,
+      a14 = 1,
+      a15 = 1,
+      a16 = 1,
+      a17 = 1,
+      a18 = 1,
+      a19 = 1,
+      a20 = 1,
+      a21 = 1,
+      a22 = 1,
+      a23 = 1,
+      a24 = 1,
+      a25 = 1,
+      a26 = 1,
+      a27 = 1,
+      a28 = 1,
+      a29 = 1,
+      a30 = 1,
+      a31 = 1,
+      a32 = 1,
+      a33 = 1,
+      a34 = 1,
+      a35 = 1,
+      a36 = 1,
+      a37 = 1,
+      a38 = 1,
+      a39 = 1,
+      a40 = 1,
+      a41 = 1,
+      a42 = 1,
+      a43 = 1,
+      a44 = 1,
+      a45 = 1,
+      a46 = 1,
+      a47 = 1,
+      a48 = 1,
+      a49 = 1,
+      a50 = 1,
+      a51 = 1,
+      a52 = 1,
+      a53 = 1,
+      a54 = 1,
+      a55 = 1,
+      a56 = 1,
+      a57 = 1,
+      a58 = 1,
+      a59 = 1,
+      a60 = 1,
+      a61 = 1,
+      a62 = 1,
+      a63 = 1
+    }
diff --git a/src/Data/Records/Yarl/LinkedList.hs b/src/Data/Records/Yarl/LinkedList.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Records/Yarl/LinkedList.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+-- |
+-- Module        : Data.Records.Yarl.LinkedList
+-- Copyright     : Gautier DI FOLCO
+-- License       : BSD3
+--
+-- Maintainer    : Gautier DI FOLCO <gautier.difolco@gmail.com>
+-- Stability     : Unstable
+-- Portability   : not portable
+--
+-- Add empty endpoint (for Health check tests)
+--
+-- Example:
+--
+-- > import Data.Records.Yarl.LinkedList
+-- >
+-- > type Person = Record '[Field "name" String, Field "age" Int]
+-- >
+-- > marvin :: Person
+-- > marvin = Field "marvin" :> Field 42 :> RNil
+-- >
+-- > desc :: Person -> String
+-- > desc p = "My name is " <> p.name <> " and I'm " <> show p.age
+--
+module Data.Records.Yarl.LinkedList
+  ( Record (..),
+    Field (..),
+    HasField (..),
+  )
+where
+
+import Data.Kind
+import GHC.Records
+import GHC.TypeLits
+
+-- | Watch for field name duplication
+type family HasNotField (target :: Symbol) (names :: [Type]) :: Constraint where
+  HasNotField x '[] = ()
+  HasNotField x (Field x v ': ys) = TypeError ('Text "Field already declared: " ':<>: 'ShowType x)
+  HasNotField x (Field y v ': ys) = HasNotField x ys
+
+-- | Field container
+newtype Field (name :: Symbol) a = Field {fieldValue :: a}
+
+-- | Full extensible record
+data Record :: [Type] -> Type where
+  RNil :: Record '[]
+  (:>) :: HasNotField fieldName fields => Field fieldName a -> Record fields -> Record (Field fieldName a : fields)
+
+infixr 5 :>
+
+instance {-# OVERLAPS #-} HasField fieldName (Record (Field fieldName a ': otherFields)) a where
+  getField (Field x :> _) = x
+  {-# INLINE getField #-}
+
+instance
+  HasField fieldName (Record otherFields) a =>
+  HasField fieldName (Record (headField ': otherFields)) a
+  where
+  getField (_ :> otherFields) = getField @fieldName otherFields
+  {-# INLINE getField #-}
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/yarl.cabal b/yarl.cabal
new file mode 100644
--- /dev/null
+++ b/yarl.cabal
@@ -0,0 +1,136 @@
+cabal-version:       3.0
+name:                yarl
+version:             0.1.0.0
+author:              Gautier DI FOLCO
+maintainer:          gautier.difolco@gmail.com
+category:            Data
+build-type:          Simple
+license:             ISC
+license-file:        LICENSE
+synopsis:            Yet another recrds libraries
+description:         Yet another recrds libraries (with getField support)
+Homepage:            http://github.com/blackheaven/yarl
+tested-with:         GHC==9.2.4
+
+library
+  default-language:   Haskell2010
+  build-depends:
+      base == 4.*
+  hs-source-dirs: src
+  exposed-modules:
+      Data.Records.Yarl.LinkedList
+  other-modules:
+      Paths_yarl
+  autogen-modules:
+      Paths_yarl
+  default-extensions:
+      DataKinds
+      DefaultSignatures
+      DeriveAnyClass
+      DeriveGeneric
+      DerivingStrategies
+      DerivingVia
+      DuplicateRecordFields
+      FlexibleContexts
+      GADTs
+      GeneralizedNewtypeDeriving
+      KindSignatures
+      LambdaCase
+      OverloadedLists
+      OverloadedStrings
+      OverloadedRecordDot
+      RankNTypes
+      RecordWildCards
+      ScopedTypeVariables
+      TypeApplications
+      TypeFamilies
+      TypeOperators
+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints
+
+test-suite librarian-test
+  type: exitcode-stdio-1.0
+  hs-source-dirs: test
+  main-is: Spec.hs
+  other-modules:
+      -- LibrarianSpec
+      Paths_yarl
+  autogen-modules:
+      Paths_yarl
+  default-extensions:
+      DataKinds
+      DefaultSignatures
+      DeriveAnyClass
+      DeriveGeneric
+      DerivingStrategies
+      DerivingVia
+      DuplicateRecordFields
+      FlexibleContexts
+      GADTs
+      GeneralizedNewtypeDeriving
+      KindSignatures
+      LambdaCase
+      OverloadedLists
+      OverloadedStrings
+      OverloadedRecordDot
+      RankNTypes
+      RecordWildCards
+      ScopedTypeVariables
+      TypeApplications
+      TypeFamilies
+      TypeOperators
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints
+  build-depends:
+      base
+    , yarl
+    , hspec
+    , hspec-core
+    , hspec-discover
+  default-language: Haskell2010
+
+benchmark bench
+  type: exitcode-stdio-1.0
+  hs-source-dirs: bench
+  main-is: Main.hs
+  default-language:   Haskell2010
+  other-modules:
+      PlainRecord.Type
+      PlainRecord.Value
+      PlainRecord.ScenarioDirect
+      PlainRecord.ScenarioGetValueConcrete
+      PlainRecord.ScenarioGetValueClass
+      LinkedList.Type
+      LinkedList.Value
+      LinkedList.ScenarioDirect
+      LinkedList.ScenarioGetValueConcrete
+      LinkedList.ScenarioGetValueClass
+      Paths_yarl
+  autogen-modules:
+      Paths_yarl
+  default-extensions:
+      DataKinds
+      DefaultSignatures
+      DeriveAnyClass
+      DeriveGeneric
+      DerivingStrategies
+      DerivingVia
+      DuplicateRecordFields
+      FlexibleContexts
+      GADTs
+      GeneralizedNewtypeDeriving
+      KindSignatures
+      LambdaCase
+      OverloadedLists
+      OverloadedStrings
+      OverloadedRecordDot
+      RankNTypes
+      RecordWildCards
+      ScopedTypeVariables
+      TypeApplications
+      TypeFamilies
+      TypeOperators
+  ghc-options: -Wall -fwarn-tabs -O2 -threaded -rtsopts -with-rtsopts=-N -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints
+  build-depends:
+      base
+    , yarl
+    , criterion
+    , deepseq
