Special Haskell Syntax used by IHP
IHP uses many “exotic” haskell features. Here’s a short explanation of the most common. In case you think something is missing, let us know on Slack.The hash symbols
IHP uses hash symbols# all over the place, like in this code:
OverloadedLabels language extension.
In IHP you can think of these hash-strings as immutable type-level strings. One of the most common uses for labels is to represent field names. In the above example #companyId refers to the companyId field on the Company data structure.
Technical details
Technical details
Writing So
#companyId is equivalent to writing fromLabel @"companyId". The fromLabel function is provided by a type class and can be implemented by e.g. libraries and frameworks. In IHP this instance is usually this:#companyId can be written as fromLabel @"companyId" which IHP turns into Proxy @"companyId". The Proxy value is now a normal haskell value and is passed to functions such as get or set.The dot notation .
IHP uses dot notation likesomeRecord.someField everywhere. You might not think of this as anything special, but this syntax was just recently added to Haskell.
The dot notation is provided by the OverloadedRecordDot language extension.
In IHP v0.19 and older IHP versions, the dot notation was not supported yet. So you might see
get #someField someRecord instead in older projects. The get #someField someRecord notation is equivalent to someRecord.someField and is still supported.The at symbol @
Another symbol used often in IHP is the@ symbol, like this:
Type-level lists
Type-level lists
If you have open questions about lists like
fill @["title", "body"], after reading the linked blog post:These are type-level lists. You can write @"type level strings" and type level integers like @1337, so you can also write type level lists like @["title", "body"].Be aware: When you write a type level list like @["title"], so with only a single element, you need to prepend a ' like this @'["title"]. Otherwise you’ll get an error. We opened a ticket on the haskell compiler for this already.The { .. }
Inside actions the views are usually rendered like this:
IndexView { .. } is a shortcut for IndexView { users = users }.
When the haskell compiler expands this, it will internally be like this:
Record wildcards.
The bang operator !
Inside your Web/Types.hs you see lots of !s, like this:
! marks the postId field as strict. Strict means that the value of postId is not stored as a lazy value. So instead of only computing the postId field when needed, it will already be fully computed when the ShowPostAction value is constructed. Basically we tell haskell that we’re sure that this field is always needed. This makes the action data structures more memory efficient.
You can learn more about strictness and laziness in haskell in this blog post.
The \case
Inside controllers you typically find code like this:
\case is called a Lambda case in haskell. It’s a shortcut for writing this:
\case ... can be expanded to \value -> case value of ....
The lambda case is provided by the LambdaCase language extension
Learn more about lambda cases here.
The Pipe operator |>
In IHP code bases you find lots of usage of the |> operator. We usually call it the pipe operator.
The operator allows you to write code like this:
Implementation details
Implementation details
The operator itself is defined as a haskell function inside
IHP.HaskellSupport:Tell GHC (Haskell Compiler) To Infer Constraints And Implicit Parameters
Let’s say you are working with a controllerApplicationsAction and most actions have similar access control:
?context::ControllerContext implicit: