Beta release of Hakyll 4

276 views
Skip to first unread message

Jasper Van der Jeugt

unread,
Dec 17, 2012, 11:45:02 AM12/17/12
to hakyll
Hey all,

After working on this for a long time, I think Hakyll 4 is ready for a
rough beta release. This mail is primarily meant at the users who like
learning, playing with their site configuration and are interested in
giving some feedback.

Main changes include:

- Switch from Arrow to Monad, making the Compiler type much easier to use;
- New, more flexible template system;
- Early access to Metadata (even in Rules), making things such as Tags
much less of a pain;
- Every item (images, css...) can now have metadata associated.

You can install the Hakyll 4 from the repo:

git clone --depth 5 -b hakyll4 http://github.com/jaspervdj/hakyll.git
cd hakyll
cabal install

The tutorials have been updated and can be found here for now:
http://jaspervdj.be/tmp/hakyll4/tutorials.html

I still need to write a "migration guide" and some more advanced
tutorials. In the meanwhile, any kind of comments, criticism or
questions are welcome!

Peace,
Jasper

pestaa

unread,
Dec 18, 2012, 4:45:02 AM12/18/12
to hak...@googlegroups.com
Hey Jasper,

This is very good news. I've just skimmed through the new tutorials, the load/loadAll functions seem useful. I have 300+ lines in my hakyll.hs, it might get a clean up with the new release. ;)

However the FAQ for hakyll4 describes page compiler composition via arrows. I guess it just fell through the cracks.

The monad approach does look nicer, although I'm only 3 months into Haskell, so still beating arrows to make them do what I want.

Keep up the good work.

Istvan

Jasper Van der Jeugt

unread,
Dec 18, 2012, 9:04:41 AM12/18/12
to hak...@googlegroups.com
Hello Paul,

> glad to see a new major release in the pipe. And glad to see the interface
> revisited, as I have never really appreciated the arrow one :)

Thanks!

> A few years ago we discussed the rational behind the Arrow interface, and
> you said it was required for some sort of static analysis / guaranties for
> the compiler. So I am curious, may I ask what happened to this approach ? Is
> there a trade-off to the new monad-based interface ?

Yes. The change to a monad-based interface came with two drawbacks.

- A lot of information has to be persisted between runs, including
Patterns. This means we could no longer have arbitrary predicates
(`predicate :: (Identifier -> Bool) -> Pattern`). To compensate, other
pattern constructors were added.

- Metacompilers are no longer possible. However, I think this might be
good thing since they were overly complicated. Things that used to
require metacompilers can now be implemented using the early metadata
access primitives.

> Also, in the "compilers" doc page, I see "titleContext :: Context a", but
> shouldn't that be "Context String" ?

That would also work, but `titleContext` is a `Context` that works for
every type since it only operates on the `Metadata` and not the value
of the body (of type `a`): `titleContext` can also work if you're
compiling a `ByteString` or an image or...

Cheers,
Jasper

On Tue, Dec 18, 2012 at 2:33 PM, <paul....@gmail.com> wrote:
> Hello Jasper,
>
> glad to see a new major release in the pipe. And glad to see the interface
> revisited, as I have never really appreciated the arrow one :)
>
> A few years ago we discussed the rational behind the Arrow interface, and
> you said it was required for some sort of static analysis / guaranties for
> the compiler. So I am curious, may I ask what happened to this approach ? Is
> there a trade-off to the new monad-based interface ?
>
> Also, in the "compilers" doc page, I see "titleContext :: Context a", but
> shouldn't that be "Context String" ?
>
> regards,

Jasper Van der Jeugt

unread,
Dec 29, 2012, 1:35:50 PM12/29/12
to hak...@googlegroups.com
I added another useful feature to (the not yet released) Hakyll 4. In
addition to `build`, `preview`... we now also have

./site check

which will check all HTML files in the _site/ directory. Currently the
only implemented check is validating all internal (does the file
exist) and external (using `http-conduit`) links. I might add more
checks in the future.

Peace,
Jasper

Bernardo Barros

unread,
Dec 29, 2012, 2:07:53 PM12/29/12
to hak...@googlegroups.com
On 29/12/12 15:35, Jasper Van der Jeugt wrote:
> which will check all HTML files in the _site/ directory. Currently the
> only implemented check is validating all internal (does the file
> exist) and external (using `http-conduit`) links. I might add more
> checks in the future.

Great, very handy. Would be nice an option for html5 too (if it's not
automatically checked).

Jasper Van der Jeugt

unread,
Jan 3, 2013, 10:20:05 AM1/3/13
to hak...@googlegroups.com
The following should work:

match ("static/**" `mappend` complement "static/css/**")

The Monoid instance for Pattern works as an "and" algebra: `mempty`
matches everything and `mappend` translates to &&. Additionally,
complement is like `not`.

The reason arbitrary predicates are no longer allowed is that we need
to serialize them in a number of places.

Hope this helps,
Peace,
Jasper

On Thu, Jan 3, 2013 at 4:12 PM, <dee...@soundcloud.com> wrote:
>
>
> On Monday, December 17, 2012 5:45:02 PM UTC+1, jaspervdj wrote:
>>
>>
>> After working on this for a long time, I think Hakyll 4 is ready for a
>> rough beta release. This mail is primarily meant at the users who like
>> learning, playing with their site configuration and are interested in
>> giving some feedback.
>>
>>
>
> Any suggestions on how I can implement something like this, that worked in
> Hakyll 3, but fails to compile on Hakyll4.
>
> match (predicate (\i -> matches "static/**" i && not (matches
> "static/css/**" i)))
>
> I guess I can separate out my CSS folder in the worst case. Any alternate
> suggestions are appreciated.
>
>

Roman Cheplyaka

unread,
Jan 3, 2013, 12:26:05 PM1/3/13
to hak...@googlegroups.com
And is there a way to "or" two patterns, short of using the De Morgan's
laws? :-)

* Jasper Van der Jeugt <m...@jaspervdj.be> [2013-01-03 16:20:05+0100]

Jasper Van der Jeugt

unread,
Jan 3, 2013, 1:04:37 PM1/3/13
to hak...@googlegroups.com
Nope, that was missing. I just added:

(.||.) :: Pattern -> Pattern -> Pattern
(.&&.) :: Pattern -> Pattern -> Pattern

which provide nicer syntax, e.g. the example discussed above becomes:

match ("static/**" .&&. complement "static/css/**")

Hope this helps,
Peace,
Jasper

Jasper Van der Jeugt

unread,
Jan 6, 2013, 2:49:18 AM1/6/13
to hak...@googlegroups.com, dee...@soundcloud.com
Hello,

It's indeed an issue. I thought it would be nicer for end users to use
`match` in both cases, but it makes the semantics a bit more vague. It
looks like it would be better to remove this feature and add `create`
again.

Peace,
Jasper

On Sun, Jan 6, 2013 at 1:15 AM, <dupl...@yahoo.com.br> wrote:
>
>
> On Saturday, January 5, 2013 12:24:02 PM UTC-2, dee...@soundcloud.com wrote:
>>
>>
>> I noticed something that was a bit intuitive for me.
>>
>> In some cases. the 'match' function seems to work differently when it
>> takes a pattern constructed from 'fromGlob', as opposed to when the pattern
>> constructed from 'fromList'. To illustrate with an example, here [1] is the
>> code which works for me. Notice the use of forM_ and the use of 'match
>> (fromGlob b)' in the argument to forM_. I wanted to simplify it by just
>> using 'match (fromList ["identifier1", "identifier2"])' but that does not
>> work for this specific cases. The only interesting thing I am doing is that
>> I am constructing the pages with 'makeItem'. I did not dig too deep in the
>> code to figure out why it behaves differently. Maybe it is a bug?
>>
>> [1] https://github.com/deepakjois/website/blob/hakyll4/src/Site.hs#L50
>
>
> I was looking for a way to create pages from scratch as you did there, and
> this forM_ workaround worked like a charm, thanks! As for why it works, if I
> understood it correctly it is due to Hakyll.Core.Rules.flush [1]. According
> to lines 89-93, literal patterns are "accepted" unconditionally, while
> non-literals (fromList patterns, globs with wildcards, etc.) are ignored
> unless they match an actual file in the site source tree (getMatches, at
> line 91).
>
> [1]
> https://github.com/jaspervdj/hakyll/blob/hakyll4/src/Hakyll/Core/Rules.hs#L79

Jasper Van der Jeugt

unread,
Jan 6, 2013, 4:03:32 AM1/6/13
to hak...@googlegroups.com, dee...@soundcloud.com
Hello,

There are now two distinct functions.

match :: Pattern -> Rules () -> Rules ()
create :: [Identifier] -> Rules () -> Rules ()

`create` always compiles the given identifiers, and match only
compiles matching files in the project directory. I've opted to have
it take a list of identifiers instead of a single one, this should
make it look nicer in scenarios such as discussed above (e.g.
bookPages here:
https://github.com/deepakjois/website/blob/hakyll4/src/Site.hs#L50)

I hope this makes it cleaner/more straightforward to use? Criticism welcome.

Peace,
Jasper

Jasper Van der Jeugt

unread,
Jan 14, 2013, 9:19:55 AM1/14/13
to hak...@googlegroups.com
I will release Hakyll 4 this week.

- The old site will remain available at: http://jaspervdj.be/hakyll/hakyll3/
- The new site is available at: http://jaspervdj.be/hakyll/hakyll4/
- A migration guide is available here:
http://jaspervdj.be/hakyll/hakyll4/tutorials/hakyll-3-to-hakyll4-migration-guide.html

Both /hakyll3 and /hakyll4 will continue to exist, and
http://jaspervdj.be/hakyll host the same contents as /hakyll4 soon.

I'd be glad to hear if anyone finds anything missing in the migration
guide. Since so much has changed, there's no magic bullet, and I will
probably just include all common problems as subsections.

Peace,
Jasper

On Sun, Jan 6, 2013 at 10:26 AM, Daniel Mlot <dupl...@yahoo.com.br> wrote:
> Works fine here, and looks much nicer. Thanks for the very quick fix!

Mark Reid

unread,
Jan 15, 2013, 9:45:34 PM1/15/13
to hak...@googlegroups.com
Hi,

Based on my recent usage of Hakyll 4, I have a suggestion to add a `joinTemplateList` function that joins a list of items with a given delimiter:

   import Data.List (intersperse)

   joinTemplateList :: Template -> Context a -> [Item a] -> String -> Compiler String
   joinTemplateList tpl context items delimiter = do
     items' <- mapM (applyTemplate tpl context) items
     return $ concat $ intersperse delimiter $ map itemBody items'

Regards,

Mark

Jasper Van der Jeugt

unread,
Jan 16, 2013, 4:52:00 AM1/16/13
to hak...@googlegroups.com
Hello,

Makes sense, I added it now [1]. The name and signature is slightly
different, though.

[1]: https://github.com/jaspervdj/hakyll/commit/652ceb03f1185ad8d41e7a3b91f00e1064bdd4ba#L1R42

Peace,
Jasper
Reply all
Reply to author
Forward
0 new messages