Skip to content

Instantly share code, notes, and snippets.

@chrisdone
Last active August 12, 2019 09:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisdone/5ff08e5ae4dda29d8eb0ae8a7aa26a3a to your computer and use it in GitHub Desktop.
Save chrisdone/5ff08e5ae4dda29d8eb0ae8a7aa26a3a to your computer and use it in GitHub Desktop.
forms experimentation type family
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
import Data.Bifunctor
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NE
import Text.Read
data HtmlT (m :: * -> *) a
data Form index a where
-- Values
PureValue :: FormMonad index a -> Form index a
MapValue :: (a -> b) -> Form index a -> Form index b
ApValue :: Form index (a -> b) -> Form index a -> Form index b
-- Views
PureView :: FormMonad index (View index) -> Form index a
MapView :: (View index -> View index') -> Form index a -> Form index' a
-- Fields
PureField :: FormMonad index (Field index a) -> Form index a
-- Validation/errors
Validate :: (a -> FormMonad index (Either (Error index) b)) -> Form index a -> Form index b
MapError :: (Error index -> Error index') -> Form index a -> Form index' a
instance Functor (Form i) where fmap = MapValue
instance (FormMonadic i, Monad (FormMonad i)) => Applicative (Form i) where
(<*>) = ApValue
pure = PureValue . pure
class FormField index a where
type Field index a
class FormMonadic index where
type FormMonad index :: * -> *
class FormView index where
type View index
class FormError index where
type Error index
data App
data MyError = GeneralError String
instance FormView App where type View App = HtmlT IO ()
instance FormError App where type Error App = MyError
instance FormMonadic App where type FormMonad App = IO
instance FormField App ty where type Field App ty = AppField ty
data AppField a where TextField :: AppField String
data WiderApp
data WiderError = MyError MyError
instance FormView WiderApp where type View WiderApp = HtmlT IO ()
instance FormError WiderApp where type Error WiderApp = WiderError
instance FormMonadic WiderApp where type FormMonad WiderApp = IO
demo :: Form WiderApp Int
demo = mapView (\x -> x) $ MapError MyError demoinner
demoinner :: Form App Int
demoinner = Validate (pure . first GeneralError . readEither) (PureField (pure TextField))
mapView ::
(View index -> View index)
-> Form index a
-> Form index a
mapView = MapView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment