1

The following:

instance View EditView where
    html EditView { .. } = [hsx|
        <nav>
            <ol class="breadcrumb">
                <li class="breadcrumb-item"><a href={PostsAction}>Posts</a></li>
                <li class="breadcrumb-item active">Edit Post</li>
            </ol>
        </nav>
        <h1>Edit Post</h1>
        {renderForm post}
    |]

is from the code for the Blog project in the Creating Your First Project section of the IHP guide.

I've mostly converted it from HSX to blaze-html here:

instance View EditView where
    html EditView { .. } = do
        H.nav $ do
            H.ol ! A.class_ "breadcrumb" $ do
                H.li ! A.class_ "breadcrumb-item" $ do
                    H.a ! A.href "PostsAction" $ do
                        "Posts"
                H.li ! A.class_ "breadcrumb-item active" $ do
                    "Edit Post"
        H.h1 "Edit Post"
        renderForm post

The last bit I'm wondering about is this one:

<a href={PostsAction}>Posts</a>

If I do the following:

H.a ! A.href PostsAction $ do
    "Posts"

I get this message:

• Couldn't match expected type ‘H.AttributeValue’
              with actual type ‘PostsController’
• In the first argument of ‘A.href’, namely ‘PostsAction’
  In the second argument of ‘(!)’, namely ‘A.href PostsAction’
  In the expression: H.a ! A.href PostsActiontypecheck
PostsAction
Defined at /home/dharmatech/Dropbox/Documents/ihp-blog/blog/Web/Types.hs:13:7

What's a good way to pass PostsAction to A.href?

(If there are other ways to make the blaze-html expression more idiomatic, feel free to recommend as well. :-))

Update 1

When I use the following, along the lines of what Willem suggested in his answer below:

instance View EditView where
    html EditView { .. } = do
        H.nav $ do
            H.ol ! A.class_ "breadcrumb" $ do
                H.li ! A.class_ "breadcrumb-item" $ do
                    H.a ! A.href (fromString (show PostsAction)) $ do
                        "Posts"
                H.li ! A.class_ "breadcrumb-item active" $ do
                    "Edit Post"
        H.h1 "Edit Post"
        renderForm post

I get the following:

• Couldn't match type ‘Text’ with ‘[Char]’
  Expected type: String
    Actual type: Text
• In the first argument of ‘fromString’, namely
    ‘(show PostsAction)’
  In the first argument of ‘A.href’, namely
    ‘(fromString (show PostsAction))’
  In the second argument of ‘(!)’, namely
    ‘A.href (fromString (show PostsAction))’typecheck

Perhaps I need to import a Text version of fromString?

Update 2

I've added the following import:

import Data.String(IsString(fromString))

However, the error message is the same:

• Couldn't match type ‘Text’ with ‘[Char]’
  Expected type: String
    Actual type: Text
• In the first argument of ‘fromString’, namely
    ‘(show PostsAction)’
  In the first argument of ‘A.href’, namely
    ‘(fromString (show PostsAction))’
  In the second argument of ‘(!)’, namely
    ‘A.href (fromString (show PostsAction))’typecheck

Update 3

If I hover over show the following signature is shown:

show :: forall a. Show a => a -> Text

And for fromString:

fromString :: forall a. IsString a => String -> a

So I believe that's where the mismatch is.

Update 4

This being a typical IHP view file, I have the following at the top for imports:

module Web.View.Posts.Edit where
import Web.View.Prelude

import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
dharmatech
  • 8,979
  • 8
  • 42
  • 88

1 Answers1

1

As the documentation on Inline Haskell says:

If the variable is another HSX expression, a blaze HTML element, a text or string: it is just included as you would expect.

If the variable is any other custom Haskell data structure: it will first be converted to a string representation by calling show on it. You can add a custom ToHtml (import it from IHP.HSX.ToHtml) instance, to customize rendering a data structure.

So unless there was a ToHTML in the [hsx|…] quasiquoter for {PostAction}, you thus should apply show, next we call fromString :: IsString a => String -> a to it to convert it to an AttributeValue.

The code is thus equivalent to:

instance View EditView where
    html EditView { .. } = do
        H.nav $ do
            H.ol ! A.class_ "breadcrumb" $ do
                H.li ! A.class_ "breadcrumb-item" $ do
                    H.a ! A.href (fromString (show PostsAction)) $ do
                        "Posts"
                H.li ! A.class_ "breadcrumb-item active" $ do
                    "Edit Post"
        H.h1 "Edit Post"
        renderForm post
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 1
    Great answer, thank you Willem. Bought you a coffee https://www.buymeacoffee.com/hapytex/c/1885085. – dharmatech Aug 28 '21 at 19:54
  • Willem, when I use what you suggested above, I get an error regarding `fromString`. I've updated the question with the details. Perhaps I need to import something? – dharmatech Aug 29 '21 at 01:07
  • 1
    @dharmatech: did you import `fromString` from the `IsString` typeclass? so `import Data.String(IsString(fromString))`? – Willem Van Onsem Aug 29 '21 at 07:41
  • Willem, OK I've added that import to my file. However, I'm getting the same error message. (See `Update 2` on the question above.) – dharmatech Aug 29 '21 at 09:11
  • Willem, see `Update 3` as well. I show there where it seems the type mismatch is. – dharmatech Aug 29 '21 at 09:14
  • 1
    @dharmatech: ah but you use a `show` that produces a `Text` whereas it should be the [**`show :: Show a => a -> String`**](https://hackage.haskell.org/package/base-4.15.0.0/docs/Prelude.html#v:show) from the prelude. – Willem Van Onsem Aug 29 '21 at 09:32
  • Willem, well, I'm using IHP which it appears sets things up so that `show` produces `Text`. See `Update 4` above for details about my imports. Do you have a suggestion for a way to use the prelude version of show for just this one expression? – dharmatech Aug 29 '21 at 09:36
  • 1
    @dharmatech: you can `import Prelude as P` and then work with `P.show`. – Willem Van Onsem Aug 29 '21 at 09:38
  • That works perfectly! Thank you for your help and patience, Willem. Another coffee has been sent your way. :-) – dharmatech Aug 29 '21 at 09:41