Everything was working great up until about a month or so ago...
Suddenly I'm getting
berkson.github.io/source/blog.hs: 333, 42
• Couldn't match type ‘unordered-containers-0.2.7.1:Data.HashMap.Base.HashMap
text-1.2.2.1:Data.Text.Internal.Text
aeson-0.11.2.0:Data.Aeson.Types.Internal.Value’
with ‘M.Map [Char] [Char]’
Expected type: M.Map [Char] [Char]
Actual type: Metadata
• In the first argument of ‘(M.!)’, namely ‘md’
In the first argument of ‘(++)’, namely ‘(md M.! "author")’
In the second argument of ‘(++)’, namely ‘(md M.! "author") ++ "/"’
From the code:
directorizeDateAndAuthor :: Routes
directorizeDateAndAuthor = metadataRoute $ \md ->
gsubRoute "/[0-9]{4}-[0-9]{2}-[0-9]{2}-" $ \s ->
replaceAll "-" (const "/") s ++ (md M.! "author") ++ "/"
I was wondering if you'd mind helping me decipher what exactly it's telling me? I get that there's some type of syntax error on my end, but I don't understand what changed and why it's not compiling like it used to?
Ref: https://github.com/berkson/berkson.github.io/blob/source/source/blog.hs#L330
Before hakyll 4.8 the Metadata
type synonym was defined as follows:
type Metadata = HashMap.Map String String
The metadata were just a flat list of key – value pairs.
In hakyll 4.8, metadata parsing was changed (issue, commit, release anouncement) to use YAML parser, to allow more complex metadata structure. Now, the type synonym is following:
type Metadata = Aeson.Object
This is the Object
from aeson
package – Data.Yaml
library shares the types.
Unfortunately, handling the Aeson.Object
is not as straightforward as the Map
was. To learn how to use Aeson properly, you can read a lengthy tutorial.
Luckily, Jasper provided us with a function lookupString
which is almost a drop-in replacement of HashMap.!
:
(!) :: Metadata -> String -> String
lookupString :: String -> Metadata -> Maybe String
Unwrapping the Maybe value, you will then get something like the following code:
directorizeDateAndAuthor :: Routes
directorizeDateAndAuthor = metadataRoute $ \md ->
case lookupString "author" md of
Just author ->
gsubRoute "/[0-9]{4}-[0-9]{2}-[0-9]{2}-" $ \s ->
replaceAll "-" (const "/") s ++ author ++ "/"
Nothing -> error "The author metadata field is missing."