MyNixOS website logo
Description

Type-level functions for record types.

Type Machine

TypeScript offers Utility Types, which allows creating a type from another. There is no way of doing this in Haskell. You have to maintain all your types yourselves, and handle conversions from one to another yourself.

type-machine brings a solution to this problem. Using Template Haskell, generate new types using Type-Script-inspired functions like omit, pick and record. It can also generate a conversion type-class that allows you to access fields and convert one type to another.

  • Requirements
    • Requires a couple of language extensions (see example)
    • Input ADT must have exactly one record constructor
  • Limitations
    • Does not support type parameters yet
    • require and partial only work with Maybe fields

Examples

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DuplicateRecordFields #-}

data User = User {
    id :: Int,
    name :: String,
    email :: Maybe String
}

$(type_ "UserWithEmail" (required ["email"] <::> ''User))
-- data UserWithEmail = UserWithEmail {
--     id :: Int,
--     name :: String,
--     email :: String
-- }

$(type_ "UserWithoutId" (omit ["id"] <::> ''User))
-- data UserWithoutId = UserWithoutId {
--     name :: String,
--     email :: String
-- }

$(type_ "UserId" (pick ["id"] <::> ''User))
-- data UserId = UserId {
--     id :: Int
-- }

$(type_ "Vector3" (record ["x", "y", "z"] [t|Int|]))
-- data Vector3 = Vector3 {
--     x :: Int,
--     y :: Int,
--     z :: Int
-- }

-----
-- Type Parameters
-----

data MyMaybe a = { content :: Maybe a }

$(type_ "MyString" (apply [t|String|] <::> ''MyMaybe))
-- data MyString = MyString { 
--     content :: Maybe String
-- }

-----
-- Is
-----

$(declareIs ''User)
-- class IsUser a where
--     getId :: a -> Int
--     getName :: a -> String
--     getEmail :: a -> String
--     setId :: Int -> a -> a
--     setName :: String -> a -> a
--     setEmail :: String -> a -> a
--
-- instance IsUser User where
--     getId = id
--     getName = name
--     getEmail = email
--     setId = ...
--     setName = ...
--     setEmail = ...

$(type_ "UserWithoutEmail" (omit ["email"] <::> ''User))
$(deriveIs ''User ''UserWithoutEmail)
-- instance IsUser UserWithoutEmail where
--     ...

$(type_ "UserWithoutId" (omit ["id"] <::> ''User))
$(deriveIs ''User ''UserWithoutId) -- Will fail
Metadata

Version

0.1.0.2

Platforms (76)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-freebsd
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64-windows
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-linux
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows