Simulating Scala return with Either

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
{-# LANGUAGE EmptyDataDecls #-}

import Control.Monad.Error

data DAO
data Form
data Action
data Model
data Request
data FormBindError
data BoundForm
data OrderNum
data TransError
data TransID
data DAOErr
data Foo
data Bar
data Baz
data Etc

dao :: DAO
dao = undefined

form :: Form
form = undefined

bindFormRequest :: Request -> Form -> Either FormBindError BoundForm
bindFormRequest = undefined

processPayment :: Model -> OrderNum -> Either TransError TransID
processPayment = undefined

withForm :: BoundForm -> Action
withForm = undefined

getModel :: BoundForm -> Model
getModel = undefined

generateOrderNum :: OrderNum
generateOrderNum = undefined

withGlobalError :: Etc -> BoundForm -> BoundForm
withGlobalError = undefined

getHeader :: String -> Request -> String
getHeader = undefined

createMember :: Model -> String -> OrderNum -> TransID
             -> DAO -> Either DAOErr (Foo, Bar, Baz)
createMember = undefined

allGood :: Foo -> Bar -> Baz -> Action
allGood = undefined

etc :: Etc
etc = undefined

getSomeForm :: FormBindError -> BoundForm
getSomeForm = undefined


unEither :: Either a a -> a
unEither (Left a) = a
unEither (Right a) = a

onLeft :: Either l r -> (l -> l') -> Either l' r
(Left l)  `onLeft` f = Left (f l)
(Right r) `onLeft` _ = Right r


save :: Request -> Action
save request = unEither $ do
  bound <- bindFormRequest request form
           `onLeft` (\err -> withForm (getSomeForm err))

  let model = getModel bound
  let orderNum = generateOrderNum
  transID <- processPayment model orderNum
             `onLeft` (\err -> withForm (withGlobalError etc bound))

  let ip = getHeader "X-Forwarded-For" request
  (foo, bar, baz) <- createMember model ip orderNum transID dao
                     `onLeft` (\err -> withForm (withGlobalError etc bound))
  
  return $ allGood foo bar baz
74:22: Warning: Avoid lambda
Found:
\ err -> withForm (getSomeForm err)
Why not:
withForm . getSomeForm