annotate .cms/lib/codemirror/mode/haskell-literate/index.html @ 1:1d486627aa1e draft default tip

24.10
author Coffee CMS <info@coffee-cms.ru>
date Sat, 12 Oct 2024 02:51:39 +0000
parents 78edf6b517a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
1 <!doctype html>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
2
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
3 <title>CodeMirror: Haskell-literate mode</title>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
4 <meta charset="utf-8"/>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
5 <link rel=stylesheet href="../../doc/docs.css">
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
6
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
7 <link rel="stylesheet" href="../../lib/codemirror.css">
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
8 <script src="../../lib/codemirror.js"></script>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
9 <script src="haskell-literate.js"></script>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
10 <script src="../haskell/haskell.js"></script>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
11 <style>.CodeMirror {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
12 border-top : 1px solid #DDDDDD;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
13 border-bottom : 1px solid #DDDDDD;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
14 }</style>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
15 <div id=nav>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
16 <a href="https://codemirror.net/5"><h1>CodeMirror</h1><img id=logo
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
17 src="../../doc/logo.png"></a>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
18
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
19 <ul>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
20 <li><a href="../../index.html">Home</a>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
21 <li><a href="../../doc/manual.html">Manual</a>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
22 <li><a href="https://github.com/codemirror/codemirror5">Code</a>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
23 </ul>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
24 <ul>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
25 <li><a href="../index.html">Language modes</a>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
26 <li><a class=active href="#">Haskell-literate</a>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
27 </ul>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
28 </div>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
29
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
30 <article>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
31 <h2>Haskell literate mode</h2>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
32 <form>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
33 <textarea id="code" name="code">
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
34 > {-# LANGUAGE OverloadedStrings #-}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
35 > {-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
36 > import Control.Applicative ((<$>), (<*>))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
37 > import Data.Maybe (isJust)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
38
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
39 > import Data.Text (Text)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
40 > import Text.Blaze ((!))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
41 > import qualified Data.Text as T
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
42 > import qualified Happstack.Server as Happstack
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
43 > import qualified Text.Blaze.Html5 as H
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
44 > import qualified Text.Blaze.Html5.Attributes as A
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
45
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
46 > import Text.Digestive
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
47 > import Text.Digestive.Blaze.Html5
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
48 > import Text.Digestive.Happstack
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
49 > import Text.Digestive.Util
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
50
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
51 Simple forms and validation
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
52 ---------------------------
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
53
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
54 Let's start by creating a very simple datatype to represent a user:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
55
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
56 > data User = User
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
57 > { userName :: Text
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
58 > , userMail :: Text
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
59 > } deriving (Show)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
60
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
61 And dive in immediately to create a `Form` for a user. The `Form v m a` type
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
62 has three parameters:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
63
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
64 - `v`: the type for messages and errors (usually a `String`-like type, `Text` in
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
65 this case);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
66 - `m`: the monad we are operating in, not specified here;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
67 - `a`: the return type of the `Form`, in this case, this is obviously `User`.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
68
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
69 > userForm :: Monad m => Form Text m User
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
70
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
71 We create forms by using the `Applicative` interface. A few form types are
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
72 provided in the `Text.Digestive.Form` module, such as `text`, `string`,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
73 `bool`...
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
74
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
75 In the `digestive-functors` library, the developer is required to label each
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
76 field using the `.:` operator. This might look like a bit of a burden, but it
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
77 allows you to do some really useful stuff, like separating the `Form` from the
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
78 actual HTML layout.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
79
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
80 > userForm = User
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
81 > <$> "name" .: text Nothing
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
82 > <*> "mail" .: check "Not a valid email address" checkEmail (text Nothing)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
83
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
84 The `check` function enables you to validate the result of a form. For example,
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
85 we can validate the email address with a really naive `checkEmail` function.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
86
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
87 > checkEmail :: Text -> Bool
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
88 > checkEmail = isJust . T.find (== '@')
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
89
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
90 More validation
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
91 ---------------
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
92
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
93 For our example, we also want descriptions of Haskell libraries, and in order to
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
94 do that, we need package versions...
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
95
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
96 > type Version = [Int]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
97
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
98 We want to let the user input a version number such as `0.1.0.0`. This means we
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
99 need to validate if the input `Text` is of this form, and then we need to parse
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
100 it to a `Version` type. Fortunately, we can do this in a single function:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
101 `validate` allows conversion between values, which can optionally fail.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
102
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
103 `readMaybe :: Read a => String -> Maybe a` is a utility function imported from
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
104 `Text.Digestive.Util`.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
105
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
106 > validateVersion :: Text -> Result Text Version
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
107 > validateVersion = maybe (Error "Cannot parse version") Success .
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
108 > mapM (readMaybe . T.unpack) . T.split (== '.')
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
109
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
110 A quick test in GHCi:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
111
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
112 ghci> validateVersion (T.pack "0.3.2.1")
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
113 Success [0,3,2,1]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
114 ghci> validateVersion (T.pack "0.oops")
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
115 Error "Cannot parse version"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
116
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
117 It works! This means we can now easily add a `Package` type and a `Form` for it:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
118
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
119 > data Category = Web | Text | Math
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
120 > deriving (Bounded, Enum, Eq, Show)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
121
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
122 > data Package = Package Text Version Category
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
123 > deriving (Show)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
124
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
125 > packageForm :: Monad m => Form Text m Package
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
126 > packageForm = Package
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
127 > <$> "name" .: text Nothing
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
128 > <*> "version" .: validate validateVersion (text (Just "0.0.0.1"))
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
129 > <*> "category" .: choice categories Nothing
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
130 > where
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
131 > categories = [(x, T.pack (show x)) | x <- [minBound .. maxBound]]
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
132
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
133 Composing forms
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
134 ---------------
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
135
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
136 A release has an author and a package. Let's use this to illustrate the
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
137 composability of the digestive-functors library: we can reuse the forms we have
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
138 written earlier on.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
139
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
140 > data Release = Release User Package
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
141 > deriving (Show)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
142
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
143 > releaseForm :: Monad m => Form Text m Release
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
144 > releaseForm = Release
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
145 > <$> "author" .: userForm
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
146 > <*> "package" .: packageForm
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
147
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
148 Views
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
149 -----
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
150
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
151 As mentioned before, one of the advantages of using digestive-functors is
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
152 separation of forms and their actual HTML layout. In order to do this, we have
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
153 another type, `View`.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
154
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
155 We can get a `View` from a `Form` by supplying input. A `View` contains more
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
156 information than a `Form`, it has:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
157
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
158 - the original form;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
159 - the input given by the user;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
160 - any errors that have occurred.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
161
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
162 It is this view that we convert to HTML. For this tutorial, we use the
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
163 [blaze-html] library, and some helpers from the `digestive-functors-blaze`
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
164 library.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
165
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
166 [blaze-html]: http://jaspervdj.be/blaze/
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
167
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
168 Let's write a view for the `User` form. As you can see, we here refer to the
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
169 different fields in the `userForm`. The `errorList` will generate a list of
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
170 errors for the `"mail"` field.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
171
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
172 > userView :: View H.Html -> H.Html
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
173 > userView view = do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
174 > label "name" view "Name: "
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
175 > inputText "name" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
176 > H.br
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
177 >
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
178 > errorList "mail" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
179 > label "mail" view "Email address: "
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
180 > inputText "mail" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
181 > H.br
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
182
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
183 Like forms, views are also composable: let's illustrate that by adding a view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
184 for the `releaseForm`, in which we reuse `userView`. In order to do this, we
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
185 take only the parts relevant to the author from the view by using `subView`. We
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
186 can then pass the resulting view to our own `userView`.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
187 We have no special view code for `Package`, so we can just add that to
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
188 `releaseView` as well. `childErrorList` will generate a list of errors for each
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
189 child of the specified form. In this case, this means a list of errors from
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
190 `"package.name"` and `"package.version"`. Note how we use `foo.bar` to refer to
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
191 nested forms.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
192
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
193 > releaseView :: View H.Html -> H.Html
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
194 > releaseView view = do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
195 > H.h2 "Author"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
196 > userView $ subView "author" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
197 >
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
198 > H.h2 "Package"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
199 > childErrorList "package" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
200 >
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
201 > label "package.name" view "Name: "
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
202 > inputText "package.name" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
203 > H.br
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
204 >
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
205 > label "package.version" view "Version: "
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
206 > inputText "package.version" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
207 > H.br
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
208 >
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
209 > label "package.category" view "Category: "
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
210 > inputSelect "package.category" view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
211 > H.br
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
212
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
213 The attentive reader might have wondered what the type parameter for `View` is:
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
214 it is the `String`-like type used for e.g. error messages.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
215 But wait! We have
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
216 releaseForm :: Monad m => Form Text m Release
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
217 releaseView :: View H.Html -> H.Html
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
218 ... doesn't this mean that we need a `View Text` rather than a `View Html`? The
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
219 answer is yes -- but having `View Html` allows us to write these views more
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
220 easily with the `digestive-functors-blaze` library. Fortunately, we will be able
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
221 to fix this using the `Functor` instance of `View`.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
222 fmap :: Monad m => (v -> w) -> View v -> View w
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
223 A backend
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
224 ---------
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
225 To finish this tutorial, we need to be able to actually run this code. We need
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
226 an HTTP server for that, and we use [Happstack] for this tutorial. The
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
227 `digestive-functors-happstack` library gives about everything we need for this.
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
228 [Happstack]: http://happstack.com/
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
229
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
230 > site :: Happstack.ServerPart Happstack.Response
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
231 > site = do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
232 > Happstack.decodeBody $ Happstack.defaultBodyPolicy "/tmp" 4096 4096 4096
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
233 > r <- runForm "test" releaseForm
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
234 > case r of
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
235 > (view, Nothing) -> do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
236 > let view' = fmap H.toHtml view
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
237 > Happstack.ok $ Happstack.toResponse $
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
238 > template $
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
239 > form view' "/" $ do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
240 > releaseView view'
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
241 > H.br
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
242 > inputSubmit "Submit"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
243 > (_, Just release) -> Happstack.ok $ Happstack.toResponse $
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
244 > template $ do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
245 > css
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
246 > H.h1 "Release received"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
247 > H.p $ H.toHtml $ show release
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
248 >
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
249 > main :: IO ()
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
250 > main = Happstack.simpleHTTP Happstack.nullConf site
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
251
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
252 Utilities
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
253 ---------
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
254
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
255 > template :: H.Html -> H.Html
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
256 > template body = H.docTypeHtml $ do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
257 > H.head $ do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
258 > H.title "digestive-functors tutorial"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
259 > css
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
260 > H.body body
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
261 > css :: H.Html
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
262 > css = H.style ! A.type_ "text/css" $ do
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
263 > "label {width: 130px; float: left; clear: both}"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
264 > "ul.digestive-functors-error-list {"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
265 > " color: red;"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
266 > " list-style-type: none;"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
267 > " padding-left: 0px;"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
268 > "}"
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
269 </textarea>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
270 </form>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
271
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
272 <p><strong>MIME types
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
273 defined:</strong> <code>text/x-literate-haskell</code>.</p>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
274
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
275 <p>Parser configuration parameters recognized: <code>base</code> to
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
276 set the base mode (defaults to <code>"haskell"</code>).</p>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
277
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
278 <script>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
279 var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "haskell-literate"});
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
280 </script>
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
281
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
282 </article>