Skip to content

Instantly share code, notes, and snippets.

@boj
Created March 25, 2020 19:39
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 boj/b0186cc8edb80f75a53d2b979b08aea4 to your computer and use it in GitHub Desktop.
Save boj/b0186cc8edb80f75a53d2b979b08aea4 to your computer and use it in GitHub Desktop.
module Main where
import Data.Coerce
data Validated
data Unvalidated
class AbstractError e
data MyError = MyError String deriving (Show)
instance AbstractError MyError
validate
:: AbstractError e
=> (a Unvalidated -> Either e (a Validated))
-> a Unvalidated -> Either e (a Validated)
validate f v = f v
data Name a = Name String deriving (Show)
validateName :: Name Unvalidated -> Either MyError (Name Validated)
validateName n@(Name v)
| length v >= 3 = Right (coerce n)
| otherwise = Left (MyError "too short")
main :: IO ()
main = do
let n1 = validate validateName (Name "abcd")
let n2 = validate validateName (Name "a")
print n1
print n2
@sambolias
Copy link

Cool, that could work. I went the other direction and made it work with the concrete Flash type. The nice thing about having a Validate class is it lets me constrain an abstract input helper like this

validatedInputHelper :: (MonadWidget t m, Validate a)
  => m (Dynamic t (a Unvalidated))
  -> m (Event t (Either Flash (a Validated)))
validatedInputHelper input = do
  dyUnvalidated <- input
  let evValidated = fmap validate $ updated dyUnvalidated
  flashWidgetEv flashConfig $ fmap (either (Just . id) (const Nothing)) evValidated
  return evValidated

although, my end goal is to do validation and return some arbitrary number of inputs in a form, and for that to work the a in my type signature would all have to be same type so that the returns from all inputs could be put into some kind of container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment