Giter Site home page Giter Site logo

soupi / learn-haskell-blog-generator Goto Github PK

View Code? Open in Web Editor NEW
259.0 6.0 44.0 16.45 MB

Learn Haskell by building a blog generator - an introductory book about Haskell.

Home Page: https://learn-haskell.blog

License: Creative Commons Attribution Share Alike 4.0 International

haskell haskell-learning tutorial learning-haskell book mdbook

learn-haskell-blog-generator's Introduction

Hi, I'm Gil.

My GitHub profile mainly focuses on tutorials, learning resources, example projects, and contribution to other open-source projects.

If you are interested in my personal software projects, you might want to check my Gitea instance (vcs.gilmi.me/suppi) instead.

To find out more about me, visit my website: gilmi.me.

learn-haskell-blog-generator's People

Contributors

agreif avatar averm avatar cthulehansen avatar dyniec avatar etra0 avatar faris999 avatar fredhsu avatar infomiho avatar jasonu avatar leverimmy avatar nattybear avatar nosarthur avatar noughtmare avatar pennychase avatar philderbeast avatar pklinken avatar preshetin avatar refaelsh avatar sai-lalith avatar scudelletti avatar sekunho avatar soupi avatar threeearcat avatar zelenya avatar zoroqi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

learn-haskell-blog-generator's Issues

Example output uses the escape function before it has been applied to the header

When we get to this point in the tutorial, the example output shows the symbols being escaped as part of the output. However, if you are following along with the tutorial, the escape function hasn't been applied to the header yet, so this output should not have escaped characters.

"<html><head><title>&lt;title&gt;</title></head><body><p>&lt;body&gt;</p></body></html>"

Clarify "Exposing internal functionality"

Feedback from here: https://twitter.com/LambdaMan7/status/1443655806201876494

I think an important key element that I failed to communicate in that section, for the purpose of Internal modules, is that this pattern is useful for exposing implementation details - not for our project (because we can always edit the Html module directly), but for other projects that would want to use our Html module as a library.

If we were to publish our Html module as a library, users wouldn't generally download the source code and include it in their project, but rather use a package manager to download a library (as we show in a later chapter) that just exposes the API - and because the users can't edit the source for the Html module in their project, they are locked in with what we provide them with. Because we don't expose the internals for the implementation in the Html module, no new functions that have to rely on the implementation details can be created by the user in their project, they would have to fork the library or something similar.

But if we also expose the Html.Internal module that does expose the internal implementation, they can write new functions in their project as if they had access to the internals of the Html module (even if this practice is not generally recommended).

incrementChar example could be more explicit for beginners

In the Type checking with pen and paper section, I found the incrementChar note confusing. As it's written, it confused me as a runnable example. Obviously (to me now, not before), the type signatures for id, ord, and chr won't compile alone. I copy and pasted the whole incrementChar code block in and it took a bit to figure out that the error I was getting was due to those type signatures. Ironically, this is one place where the Haskell compile error is pretty informative, but I still didn't get it initially.

I would consider moving the type signatures out of the code block.

Thanks for this resource!

Section 3.4 suggestion

At the beginning of the newtype section, the following statement is made:

newtype lets us give a new name to an already existing type in a way that the two cannot mix together.

It is a bit confusing to say that it gives us a new name to an already existing type. Isn't the whole point of newtype to create a new type and not to just alias an already existing type?

It might be helpful to expand more on this or to rewrite it a bit.

Typo and question in Section 3.4

In the numbered list that walks through the type signatures in the "Chaining functions" section in 3.4, I found a couple of things:

  1. In (3) "the first arguments" should be singular
  2. I don't understand what (6) (-> ~ ->) means within the chain

Could not find module ‘Html’

Maybe I am doing something wrong in section 3.5 I created file Hmtl.hs and put it in same folder where hello.hs lives but import Htmldoesn't work
изображение

Use Text instead of String

Thank you for the great content!

The book seems to use the String type throughout. It might be better to use Text for the examples to spread the use of good practices.

Could not find module ‘Options.Applicative’

First of all, thank you very much for this book. As a newbie of Haskell, I find it having the perfect balance between breadth and depth.

When I tried to use the optparse-applicative package for CLI, my stack build gives the following error

/Users/dzhou/src/ourl/app/Main.hs:6:1: error:
    Could not find module ‘Options.Applicative’
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.
  |
6 | import Options.Applicative
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^

After some googling, I found this command, which shows that I don't have optparse-applicative installed

stack exec ghc-pkg -- list

Then I used this command to install it. However, the error still persists, maybe I still need to change some configuration?

stack install optparse-applicative

Unclear explanation of `fold` function

In section 5.1, I found the explanation of fold quite confusing and it took me a while to figure it out. I think this was because I didn't understand what t m meant in the type declaration of the function (fold :: (Foldable t, Monoid m) => t m -> m). I realized that this means a Foldable of Monoid (e.g., a List of String). Perhaps a small sentence could be added to explain that. I know it's kind of explained later when you say that t must be of kind * -> *, but explaining it directly would make it easier to follow, in my opinion. A small review of kinds could be added, actually, since it's only very briefly touched on before this point.

I would also suggest that adding a simple example here would help make it more concrete, as it's basically a few paragraphs of theory in a row with no concrete example (the examples on hoogle are good: https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Foldable.html#v:fold). Just a thought.

why _ in function names?

I might have missed this, but why are there _ after many of the functions? e.g. ol_ ul_ etc.
And thank you for the work!

Minor typo in section 3.5

Thanks for the great content.
I think there is a minor typo in section 3.5 in the following line,
Sub-directories should also be part of the name and we use . do denote a sub-directory

the line should be reading
Sub-directories should also be part of the name and we use . to denote a sub-directory

Space between ( and function?

Thank you for the interesting work
Is there a rule describing whether to include space between ( and function or not?

E.g. from https://lhbg-book.link/03-html/04-safer_construction.html solution under "The rest of the owl"

myhtml :: Html
myhtml =
  html_
    "My title"
    ( append_ <------- Space between ( and append_
      (h1_ "Heading") <------- No space bwteen ( and h1_ 
      ( append_ <------- Space between ( and append_
        (p_ "Paragraph #1")
        (p_ "Paragraph #2")
      )
    )

Minor Editing

In the 3rd Chapter, section 3.1.
I suggest a small edit with the Indentation section, specific paragraph is quoted below.
"Indentation in Haskell can be a bit tricky, but in general: code which is supposed to be part of another expression should be indented further than the beginning of that expression."
I suggest replace "another" with "some". It might be confusing for readers, also found Haskell Wikibook using similar definition they are using the word "some".

Reference
Haskell Wikibook.

Error in second solution in 5.1. Converting Markup to HTML, section Document -> Html

Minor error in second solution in chaper 5.1. Converting Markup, section Document -> Html
The current solution is:

concatStructure :: [Structure] -> Structure
concatStructure list =
  case list of
    [] ->  empty_
    x : xs -> x <> concatStructure list

but I think it should be:

concatStructure :: [Structure] -> Structure
concatStructure list =
  case list of
    [] -> empty_
    x : xs -> x <> concatStructure xs

Minor typos plus some suggestions

Thanks for writing this! You're so concise - you explain concepts in one sentence, where 100 are possible because of the depth of the topic. That takes great restraint!

Very nicely organised too.

Some typos and suggestions:

This property, of behind able to substitute the two sides of the equals sign with one another, is called referential transparency. And it is pretty unique to Haskell (and a few language that are very similar to it like PureScript and Elm)!

anonymous functions are also known as lambda functions.

Hopefully this form makes it a bit clearer why Haskell functions always take one argument and return another,...
..."and return another function"

Editorial: If we're not using lambda functions here, maybe move this section to where they are used?

Right out of the batRight off the bat

Editorial: You could make the DSL/EDSL section much shorter if you wanted.

The right-hand side of the newtype declaration describes how an expression of that type looks~~ like~~.

type, on the other hand, A type is just a name alias.

Back to newtypes.

Editorial: Why not just move the type section so this paragraph is right after where you introduce newtype?

Then the multiple patterns of a case expression will make more sense.

Editorial: Why include case statements here at all then? The pattern matching in function definitions is good for introducing the concept.

getStructureString :: Structure -> String

Oops! Structure has not been defined. Did you change from calling it Html to Structure?

p_ = Structure . el "p"

Ooo! What's this? Composing a constructor with one of our functions? Neat! You did mention that constructors were like functions, but the reader didn't know you could actually compose them. What's the effect here? (do you like the word 'wrap' for this?)

Thanks again for the content... still reading!

[question] The enum usage of `data` doesn't have type

I am reading section 4.1 and try to see the data types in GHCi. For some reason this brings up an error. The Person example works though. Is this to be expected? Many thanks

*Lib> data Booll = True |False
*Lib> :t Booll

<interactive>:1:1: error: Data constructor not in scope: Booll

*Lib> data Person = Person String Int
*Lib> :t Person
Person :: String -> Int -> Person

Minor typo in section 3.6

Under section 3.6 which explains concat, there is a typo in the following line
In our case in will flatten [String] into String
I think it should read as
In our case it will flatten [String] into String

Minor typos

First of all, great book, thank you for writing this.

Throughout reading I have kept a list of typos. To indicate the location of the typo I have just used the URL.

Hope this is useful.

Unclear refactor in exercise #2 of module 3.2

In module/chapter 3.2, the changes to the functions as part of exercise 2 are unclear to me, a beginner Haskell programmer.

Using html_ as an example, it starts out looking like this (taken from the answer to exercise 1):

html_ content = "<html>" <> content <> "</html>"

But then gets turned into this, when incorporating the function "el":

html_ = el "html"

I was confused about why the parameter "content" is missing here, and I asked a friend who explained: "It's using point-free style. We are assigning p_ to a partially applied function that takes a String." Because I've tried learning Haskell before from other resources in the past, I basically know what he means, but no such explanation is given in the book.

The more explicit way of doing it (I assume) would be:

html_ content = el "html" content

If you want the solutions in this section (and all subsequent sections) to write the functions in point-free style, I think this should be explained and justified in the book itself, not hidden away in a solution box.

Some background - when I am working through this book I don't plan on checking the solution as long as what I wrote is working correctly. So in this case, I actually got confused in module 3.4 during the explanation for chaining functions with the . operator, because the definition for p_ used there is not the same one I got working in 3.2 exercise 2. So I had to go back and check previous module to see where my solution and the book's diverged.

[4.3] deriving Semigroup instead of append_

Hi! I've done the exercise in 4.3 in a different way then the solution and I'm wondering whether it's correct too. The code compiles and seems to be working correctly, but I'm still confused by Haskell a little bit and would welcome an explanation from someone more experienced.

This is my solution:

newtype Structure = Structure String deriving Semigroup

and this is the solution from the book

instance Semigroup Structure where
  (<>) c1 c2 =
    Structure (getStructureString c1 <> getStructureString c2)

EDIT: Maybe I'll add my reasoning as to how does this work and you can confirm/clarify my thoughts :)
As I understand it, deriving is basically autogenerating the implementation of the typeclass instance if all the underlying types already have the implementation. Because Structure is wrapping a String which already is an instance of Semigroup Haskell is able to generate the implementation correctly.

Thanks in advance!

Section 4.4: Word8 definition, ansiToUbuntu errors?

In section 4.4, the introduction of Word8 comes unexpectedly. Are we to import Word8? Since we're not using Cabal, it seems proper to perhaps add:

type Word8 = Int

It looks like Solution 2's ansiToUbuntu incorrectly uses the values under Terminal.app instead of the values under Ubuntu from color chart.

Wrong specialized type of foldMap in chapter 5.1

foldMap :: (Foldable t, Monoid m) -> (a -> m) -> t a -> m

-- compare to a specialized version with:
-- - t ~ []
-- - m ~ Html.Structure
-- - a ~ Markup.Structure
foldMap
  :: (Markup.Structure -> Html.Structure)
  -> [Html.Structure]
  -> Html.Structure

In the first half, a is represented as Markup.Structure, but the t a is represented as [Html.Structure]. Maybe it's a typo? Thanks 😁

book

I have a little background in programming with JavaScript, and I'm interested in Haskell and functional programming. Is this book suitable for me?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.