[HN Gopher] Learn Haskell by building a blog generator - a proje...
       ___________________________________________________________________
        
       Learn Haskell by building a blog generator - a project-oriented
       Haskell book
        
       Author : gilmi
       Score  : 206 points
       Date   : 2022-06-08 07:50 UTC (15 hours ago)
        
 (HTM) web link (lhbg-book.link)
 (TXT) w3m dump (lhbg-book.link)
        
       | zeckalpha wrote:
       | I have found Hakyll to be useful in this space, if you want to
       | move from building your own to configuring/extending your own.
        
       | Iceland_jack wrote:
       | Oh this looks fun getStructureString and render can be defined as
       | record selectors                 newtype Structure = Structure {
       | getStructureString :: String }       newtype Html      = Html
       | { render             :: String }
       | 
       | BlockArguments let you write expressions like myhtml
       | myhtml :: Html       myhtml =         html_           "My title"
       | ( append_             (h1_ "Heading")             ( append_
       | (p_ "Paragraph #1")               (p_ "Paragraph #2")
       | )           )
       | 
       | in a more domain-specific style. De gustibus, but some may prefer
       | it to the parentheses.                 {-# Language
       | BlockArguments #-}            myhtml :: Html       myhtml =
       | html_ "My title" do           append_             do h1_
       | "Heading"             do append_                  do p_
       | "Paragraph #1"                  do p_ "Paragraph #2"
       | 
       | or using the associativity of append_ = (<>)
       | myhtml =         html_ "My title" do           h1_ "Heading" <>
       | p_ "Paragraph #1" <> p_ "Paragraph #2"            myhtml =
       | html_ "My title" do mconcat           [ h1_ "Heading"           ,
       | p_ "Paragraph #1"           , p_ "Paragraph #2"           ]
       | 
       | All examples of 'concat . map' can be replaced with.. concatMap
       | :D
        
         | Iceland_jack wrote:
         | Instead of defining append_ for structure
         | newtype Structure = Structure String            append_ ::
         | Structure -> Structure -> Structure       append_ (Structure
         | c1) (Structure c2) = Structure (c1 <> c2)            empty_ ::
         | Structure       empty_ = Structure ""
         | 
         | the <> operator (from Semigroup) can be reused by deriving it
         | via the underlying String type (edit: I see this is suggested
         | later in the tutorial).                 {-# Language
         | DerivingStrategies         #-}       {-# Language
         | GeneralizedNewtypeDeriving #-}            newtype Structure =
         | Structure String         deriving         newtype (Semigroup,
         | Monoid)            append_ :: Structure -> Structure ->
         | Structure       append_ = (<>)            empty_ :: Structure
         | empty_ = mempty
         | 
         | Semigroup and Monoid let us use a lot of standard vocabulary
         | concatStructure :: [Structure] -> Structure
         | concatStructure list =         case list of           [] ->
         | empty_           x : xs -> x <> concatStructure xs
         | 
         | becomes                 concatStructure :: [Structure] ->
         | Structure       concatStructure = mconcat
         | 
         | or                 concatStructure = fold
         | 
         | Also in the detour about kinds they are written as * while the
         | ecosystem is moving towards a more uniform Type name.
         | {-# Language StandaloneKindSignatures #-}            import
         | Data.Kind (Type)            type Tuple :: Type -> Type -> Type
         | data Tuple a b = Tuple a b            type Either :: Type ->
         | Type -> Type       data Either a b = Left a | Right b
        
           | gilmi wrote:
           | Right but the point of the book is to ease learners into the
           | language (and teach core concepts), and not throw them into
           | the deep end of it.
           | 
           | Also, I'll update the text about kinds when GHC will use Type
           | instead of * everywhere:
           | 
           | $ ghci
           | 
           | GHCi, version 9.2.2: https://www.haskell.org/ghc/ :? for help
           | 
           | l> :k (,)
           | 
           | (,) :: * -> * -> *
        
             | Iceland_jack wrote:
             | Not critiquing, I was giving a stream of consciousness
             | while reading. I enjoyed it
             | 
             | Until we get Type by default the best we can do is enable
             | NoStarIsType
        
               | gilmi wrote:
               | Thank you. I'm glad you're enjoying it. Sorry if I
               | sounded a bit aggressive here.
               | 
               | I think one of the cool things about Haskell is that
               | there's quite a high ceiling in terms of solutions you
               | can reach for. On many occasions when one get annoyed by
               | something and thinks "there must be a better way", there
               | is one.
               | 
               | You show how one with more knowledge and command of the
               | language can make it do a lot of things for free, and
               | that is very cool! But I can also see how these solutions
               | can look a bit intimidating for people with less
               | experience, and it's important to take this into account
               | as well.
               | 
               | This is kind of a double edged sword. Gotta find the
               | right balance.
        
               | Iceland_jack wrote:
               | I didn't take it as aggressive. I hope people who are
               | curious get something out of my comment but without
               | intimidating others, perhaps I write it as a bonus that
               | people can ignore if it doesn't help but you are right
               | that some people could be put off by it.
        
               | gilmi wrote:
               | Sounds like a generally reasonable approach to me.
        
       | matijash wrote:
       | This is really cool! I've been looking for something like for a
       | while - my learning path was through LYAH and Real-World Haskell
       | (also tried Haskell from the first principles but a bit too
       | extensive IMO). I think this would fit in perfectly between LYAH
       | and RWH.
       | 
       | I am using Haskell mostly for writing compilers
       | (https://github.com/wasp-lang/wasp currently), but I believe if
       | the tutorial isn't using a lot of specialized
       | libraries/frameworks (which seems to be the case from the first
       | glance), a majority of the material taught should be transferable
       | to any domain.
        
       | newaccount2021 wrote:
        
       | hans1729 wrote:
       | At first sight I've read "an object-oriented Haskell book".
       | 
       |  _[brief pause for contemplating the thought]_
       | 
       | Naturally, someone went there:
       | https://www.parsonsmatt.org/tutorials/
        
         | greymalik wrote:
         | The linked articles are actually about how to translate
         | problems from an OOP perspective into idiomatic Haskell.
        
       | ypeterholmes wrote:
       | For anyone that does decide to learn Haskell, you can easily get
       | a job afterwards working on the Cardano blockchain. Smart
       | contract devs are in high demand, and Cardano uses a variant of
       | Haskell that is relatively unique to the space.
        
       | danuker wrote:
       | How you would write tests in a real project?
       | 
       | I suppose it's not writing out the entire program and then
       | writing the tests, as seems to be implied. That would mean a lot
       | of manual testing.
       | 
       | Or is there a Haskell REPL where you can try out small pieces
       | before saving them?
        
         | rowanG077 wrote:
         | You have testing libraries in Haskell just like in every other
         | languages. For example:
         | https://hackage.haskell.org/package/tasty
        
         | gilmi wrote:
         | When you create a project description for your project (for the
         | package manager) you can define a library, executables and test
         | suites.
         | 
         | In the test suite you write your tests against the library. You
         | can do that at any stage, even before writing a line of library
         | code.
         | 
         | But yes, Haskell also has a REPL that can be used to experiment
         | with code.
        
         | lgas wrote:
         | In addition to the other good answers you've gotten, I would
         | like to point out that Haskell has QuickCheck
         | (https://hackage.haskell.org/package/QuickCheck) which, if I'm
         | not mistaken, more or less pioneered property testing. Property
         | testing libraries are available in many languages now but they
         | never seem to be as capture the magic of QuickCheck. (There's
         | also https://hackage.haskell.org/package/hedgehog which is sort
         | of a "modern alternative" to QuickCheck but I still prefer the
         | OG).
        
         | jokethrowaway wrote:
         | HUnit is a popular choice: https://mmhaskell.com/testing/test-
         | driven-development
        
         | jose_zap wrote:
         | Yes, there is GHCi, the Haskell interpreter and repl comes
         | bundled with the compiler.
         | 
         | You can load your entire project in the repl and try your
         | functions there.
        
       | _query wrote:
       | If you want to do web development with Haskell beyond building a
       | blog generator, a good starting point is IHP
       | (https://ihp.digitallyinduced.com/
       | https://github.com/digitallyinduced/ihp). IHP is Haskell's
       | version of Laravel/Rails/Django. It's really a superpower to have
       | Haskell's type system combined with the rapid development
       | approach of Rails :) (Disclaimer: I'm founder of the company that
       | makes IHP)
        
         | froza wrote:
         | I was tempted to try it, but then I saw that some core features
         | (like mysql) are for paid versions only so its a big red flag
         | already
        
           | _query wrote:
           | Mysql support is not implemented at the moment. If there's
           | someone paying for the development we could have it. You're
           | of course also free to contribute it yourself to the open
           | source version, then it wouldn't need to be part of the
           | commercial version.
           | 
           | Some more background on why IHP has a paid variant can be
           | found here: https://ihp.digitallyinduced.com/blog/6392ad84-e9
           | 6a-46ce-9ab...
        
             | rowanG077 wrote:
             | I don't get it. How can it be part of the commercial
             | version if it is not implemented.
        
               | prophesi wrote:
               | Not OP, but it sounds like MySQL support isn't out yet.
               | So I think the business plan can help them get paid to
               | implement it. No clue if that means the FOSS version
               | would receive those upstream changes once it's done.
        
           | cultofmetatron wrote:
           | software needs work and devs have bills. its unfortunate but
           | we don't have a government currently giving grants to open
           | source devs yet.
        
         | bitmapper wrote:
         | I'm really not a fan of IHP for that purpose due to how it
         | redefines so much of the Haskell Prelude without making it
         | clear it does that.
        
         | My71staccount wrote:
         | Ah, I was wondering why you post about IHP on most Haskell
         | threads here and I just noticed it is a commercial product. You
         | should probably disclose that this is an advertisement if it is
         | permitted at all.
        
           | _query wrote:
           | IHP is mostly an open source project.
           | 
           | I comment on most Haskell threads about IHP because I would
           | love to see more Haskell adoption. Most people think Haskell
           | is about Monads and Math, with IHP we want to show that
           | Haskell can be used in a very productive way to build things.
           | The comments are typically well received, so I don't see any
           | problem with this.
        
         | embwbam wrote:
         | I think IHP for learning Haskell has the same flaw that Rails
         | always did. You have no idea what is part of the language and
         | what is part of the framework. You'll get stuck once you stray
         | from the golden path.
         | 
         | I'd recommend starting with Scotty instead. It's much easier to
         | understand what it is doing. Use Lucid for HTML rendering, and
         | your choice of DB libraries (I like Selda). These all avoid
         | template haskell and don't rename any prelude functions. If you
         | add them one at a time you'll see what each one is offering and
         | understand where to go when you need to do something more
         | complicated
        
       | cosmic_quanta wrote:
       | That's the perfect learning project because there's something
       | tangible at the end.
       | 
       | Whenever the question of "How do I learn Haskell" comes up, I
       | always suggest to come up with a project that would be useful on
       | its own, regardless of the technology used to create it, and use
       | Haskell to do it. In my case it was a pandoc filter to embed
       | plots in documents (https://github.com/LaurentRDC/pandoc-plot),
       | which was ultimately useful to create my PhD dissertation.
       | 
       | There's only so much you can learn about Haskell by working
       | through toy examples.
        
         | cholantesh wrote:
         | Great project; I'd have loved to have had it when I was writing
         | my dissertation - hell, I'd have liked anything that would have
         | let me write it in vim and just generate the final submission
         | per the university's format, because I hate Word.
        
       | alephnan wrote:
       | Is the website/book/blog self-hosting?
       | 
       | https://en.wikipedia.org/wiki/Self-hosting_(compilers)
        
         | gilmi wrote:
         | No. It is built with mdbook[0].
         | 
         | [0]: https://rust-lang.github.io/mdBook
        
       | bwanab wrote:
       | If you're more inclined to visual and/or musical arts, I'd
       | recommend "Th Haskell School Of Expression" by Paul Hudak. He
       | guides you through the language and the techniques with an eye
       | for concise, expressive code that has good runtime
       | characteristics.
        
       ___________________________________________________________________
       (page generated 2022-06-08 23:01 UTC)