fromValues :: EntityDef -> Text -> Exp -> [FieldDef] -> Q [Clause]
fromValues t funName conE fields = do
    x <- newName "x"
    let funMsg = entityText t `mappend` ": " `mappend` funName `mappend` " failed on: "
    patternMatchFailure <-
      [|Left $ mappend funMsg (pack $ show $(return $ VarE x))|]
    suc <- patternSuccess fields
    return [ suc, normalClause [VarP x] patternMatchFailure ]
  where
    patternSuccess [] = do
      rightE <- [|Right|]
      return $ normalClause [ListP []] (rightE `AppE` conE)
    patternSuccess fieldsNE = do
        x1 <- newName "x1"
        restNames <- mapM (\i -> newName $ "x" `mappend` show i) [2..length fieldsNE]
        (fpv1:mkPersistValues) <- mapM mkPvFromFd fieldsNE
        app1E <- [|(<$>)|]
        let conApp = infixFromPersistValue app1E fpv1 conE x1
        applyE <- [|(<*>)|]
        let applyFromPersistValue = infixFromPersistValue applyE

        return $ normalClause
            [ListP $ map VarP (x1:restNames)]
            (foldl' (\exp (name, fpv) -> applyFromPersistValue fpv exp name) conApp (zip restNames mkPersistValues))
        where
          infixFromPersistValue applyE fpv exp name =
              UInfixE exp applyE (fpv `AppE` VarE name)
          mkPvFromFd = mkPersistValue . unHaskellName . fieldHaskell
          mkPersistValue fieldName = [|mapLeft (fieldError fieldName) . fromPersistValue|]
fromValues :: EntityDef -> Text -> Exp -> [FieldDef] -> Q [Clause]
fromValues t funName conE fields = do
    x <- newName "x"
    let funMsg = entityText t `mappend` ": " `mappend` funName `mappend` " failed on: "
    patternMatchFailure <-
      [|Left $ mappend funMsg (pack $ show $(return $ VarE x))|]
    suc <- patternSuccess fields
    return [ suc, normalClause [VarP x] patternMatchFailure ]
  where
    patternSuccess [] = do
      rightE <- [|Right|]
      return $ normalClause [ListP []] (rightE `AppE` conE)
    patternSuccess fieldsNE = do
        x1 <- newName "x1"
        restNames <- mapM (\i -> newName $ "x" `mappend` show i) [2..length fieldsNE]
        (fpv1:mkPersistValues) <- mapM mkPvFromFd fieldsNE
        app1E <- [|(<$>)|]
        let conApp = infixFromPersistValue app1E fpv1 conE x1
        applyE <- [|(<*>)|]
        let applyFromPersistValue = infixFromPersistValue applyE

        return $ normalClause
            [ListP $ map VarP (x1:restNames)]
            (foldl' (\exp (name, fpv) -> applyFromPersistValue fpv exp name) conApp (zip restNames mkPersistValues))
        where
          infixFromPersistValue applyE fpv exp name =
              UInfixE exp applyE (fpv `AppE` VarE name)
          mkPvFromFd = mkPersistValue . unHaskellName . fieldHaskell
          mkPersistValue fieldName = [|mapLeft (fieldError fieldName) . fromPersistValue|]
fromValues t funName conE fields = do
    x <- newName "x"
    let funMsg = entityText t `mappend` ": " `mappend` funName `mappend` " failed on: "
    patternMatchFailure <-
      [|Left $ mappend funMsg (pack $ show $(return $ VarE x))|]
    suc <- patternSuccess fields
    return [ suc, normalClause [VarP x] patternMatchFailure ]
  where
    patternSuccess [] = do
      rightE <- [|Right|]
      return $ normalClause [ListP []] (rightE `AppE` conE)
    patternSuccess fieldsNE = do
        x1 <- newName "x1"
        restNames <- mapM (\i -> newName $ "x" `mappend` show i) [2..length fieldsNE]
        (fpv1:mkPersistValues) <- mapM mkPvFromFd fieldsNE
        app1E <- [|(<$>)|]
        let conApp = infixFromPersistValue app1E fpv1 conE x1
        applyE <- [|(<*>)|]
        let applyFromPersistValue = infixFromPersistValue applyE

        return $ normalClause
            [ListP $ map VarP (x1:restNames)]
            (foldl' (\exp (name, fpv) -> applyFromPersistValue fpv exp name) conApp (zip restNames mkPersistValues))
        where
          infixFromPersistValue applyE fpv exp name =
              UInfixE exp applyE (fpv `AppE` VarE name)
          mkPvFromFd = mkPersistValue . unHaskellName . fieldHaskell
          mkPersistValue fieldName = [|mapLeft (fieldError fieldName) . fromPersistValue|]