Skip to content

Commit d6ba966

Browse files
authored
Merge pull request #436 from VictorCMiraldo/vcm/error-83865
Documenting two examples for `83865`; Adds `order` field to example headers
2 parents 93b0256 + b2123f9 commit d6ba966

File tree

9 files changed

+128
-4
lines changed

9 files changed

+128
-4
lines changed

CONTRIBUTING.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,16 @@ The fields in the metadata block should be:
170170
### Example Descriptions
171171

172172
Example descriptions are written in Markdown with Pandoc-style
173-
metadata, just like message descriptions. They have only the `title`
174-
field. All `.hs` files are shown in the list of files for the
173+
metadata, just like message descriptions. They have the obligatory `title`
174+
and optional `order` fields. All `.hs` files are shown in the list of files for the
175175
example. The `index.md` file should explain how the files illustrate
176176
the message.
177177

178+
Examples are ordered according to their `order` field. Examples
179+
with no explicit `order` are shown last and examples with the same
180+
`order` will be shown in an unspecified order with respect to each other,
181+
but will appear before examples with a greater order.
182+
178183
## Reference: Technology choices
179184

180185
The website generated by `message-index` uses a few JS components.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: Type Mismatch
3+
summary: You provided a value of a given type, whereas GHC expected a different type.
4+
severity: error
5+
introduced: 9.6.1
6+
---
7+
8+
GHC expected one type, but was given another. Unlike dynamically-typed programming languages,
9+
type signatures in Haskell are like a contract between the programmer and the compiler.
10+
In its simplest form, when you call a function `f` with type `a -> b`, with some argument `x`,
11+
the compiler will check whether `x` has type `a` and if that is not the case, it will trigger
12+
the type mismatch error. This case is illustrated by the `terms` example, below.
13+
14+
Type mismatch errors are quite general, however, so you will still encounter them
15+
in many other situations.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
inc :: Int -> Int
2+
inc i = i + 1
3+
4+
two = inc 1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
inc :: Int -> Int
2+
inc i = i + 1
3+
4+
two = inc "x"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
title: Values of Different Types
3+
order: 0
4+
---
5+
6+
Function `inc` has type `Int -> Int`, hence it expects an argument
7+
of type `Int`; yet, on the definition of `two` it was called with
8+
an argument of type `String`.
9+
10+
If you ever need to know the type of something, you can ask for it in `ghci`
11+
with the command `:type` (or its shorthand `:t`):
12+
13+
```
14+
ghci> :t "x"
15+
"x" :: String
16+
```
17+
18+
## Error Message
19+
20+
```
21+
Terms.hs:6:11: error: [GHC-83865]
22+
• Couldn't match type ‘[Char]’ with ‘Int’
23+
Expected: Int
24+
Actual: String
25+
• In the first argument of ‘inc’, namely ‘"x"’
26+
In the expression: inc "x"
27+
In an equation for ‘two’: two = inc "x"
28+
|
29+
4 | two = inc "x"
30+
|
31+
```
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
isNothing :: Maybe a -> Bool
2+
isNothing Nothing = True
3+
isNothing _ = False
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
isNothing :: Maybe -> Bool
2+
isNothing Nothing = True
3+
isNothing _ = False
4+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
title: Type expected, but kind received.
3+
order: 1
4+
---
5+
6+
Forgetting the type parameter to `Maybe` is the culprit, but it is only caught in the
7+
context of the the arrow in the declaration of `isNothing`, which can be confusing.
8+
The arrow (`->`) in Haskell is a _type constructor_. It takes two types
9+
of *kind* `Type`, and returns a fresh type, also of kind `Type`. That is, for `x -> y`
10+
to make any sense, GHC needs `x` and `y` to be types of kind `Type`, which is not
11+
the case in this example: `Maybe` by itself has kind `Type -> Type`.
12+
13+
If you ever need to know the kind of something, you can ask `ghci`
14+
with the `:kind` (or its shorthand `:k`), keeping in mind
15+
that `*` (pronounced "star") is a synonym for `Type`:
16+
17+
```
18+
ghci> :k (->)
19+
(->) :: * -> * -> *
20+
ghci> :k Maybe
21+
Maybe :: * -> *
22+
```
23+
24+
## Error Message
25+
26+
```
27+
Type.hs:1:14: error: [GHC-83865]
28+
• Expecting one more argument to ‘Maybe’
29+
Expected a type, but ‘Maybe’ has kind ‘* -> *’
30+
• In the type signature: isNothing :: Maybe -> Bool
31+
|
32+
1 | isNothing :: Maybe -> Bool
33+
|
34+
```

message-index/site.hs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{-# LANGUAGE DataKinds #-}
22
{-# LANGUAGE LambdaCase #-}
33
{-# LANGUAGE OverloadedStrings #-}
4+
{-# LANGUAGE TupleSections #-}
45
{-# LANGUAGE TypeApplications #-}
56
{-# LANGUAGE ViewPatterns #-}
67

@@ -9,8 +10,9 @@ import qualified Data.Aeson.KeyMap as KM
910
import Data.Binary (Binary)
1011
import Data.Data (Typeable)
1112
import Data.Foldable (for_)
13+
import Data.Function (on)
1214
import Data.Functor ((<&>))
13-
import Data.List (find, isPrefixOf, lookup, nub, sort)
15+
import Data.List (find, isPrefixOf, lookup, nub, sort, sortBy)
1416
import Data.List.NonEmpty (NonEmpty (..))
1517
import qualified Data.List.NonEmpty as NE
1618
import qualified Data.Map.Strict as Map
@@ -193,6 +195,24 @@ messageTitleField = field "title" getTitle
193195
messageCtx :: Context String
194196
messageCtx = field "id" (pure . getId) <> indexlessUrlField "url"
195197

198+
data ExampleOrder = InGroup Integer | Last
199+
deriving (Eq, Show)
200+
201+
instance Ord ExampleOrder where
202+
compare (InGroup i) (InGroup j) = compare i j
203+
compare (InGroup _) Last = LT
204+
compare Last (InGroup _) = GT
205+
compare Last Last = EQ
206+
207+
getExampleOrder :: Identifier -> Compiler ExampleOrder
208+
getExampleOrder ident = do
209+
metas <- getMetadata ident
210+
let msgId = getIdentId ident
211+
case KM.lookup "order" metas of
212+
(Just (JSON.Number i)) -> pure $ InGroup (truncate i)
213+
Just other -> fail $ "Not an integer: " ++ show other
214+
Nothing -> pure Last
215+
196216
getId :: Item a -> String
197217
getId item = fromMaybe "" $ getIdentId (itemIdentifier item)
198218

@@ -208,7 +228,11 @@ getExamples = do
208228
code <- case splitDirectories $ toFilePath me of
209229
["messages", code, "index.md"] -> pure code
210230
other -> fail $ "Not processing a message: " ++ show other
211-
loadAll $ fromGlob ("messages/" <> code <> "/*/index.*") .&&. hasNoVersion
231+
items <- loadAll $ fromGlob ("messages/" <> code <> "/*/index.*") .&&. hasNoVersion
232+
sortByM (getExampleOrder . itemIdentifier) items
233+
where
234+
sortByM :: (Monad m, Ord b) => (a -> m b) -> [a] -> m [a]
235+
sortByM f = fmap (map fst . sortBy (compare `on` snd)) . mapM (\x -> (x,) <$> f x)
212236

213237
getExampleFiles :: Compiler [Item (FilePath, Maybe (Item String), Maybe (Item String))]
214238
getExampleFiles = do

0 commit comments

Comments
 (0)