<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anay Nayak</title>
    <description>The latest articles on Forem by Anay Nayak (@anaynayak).</description>
    <link>https://forem.com/anaynayak</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F249047%2F6d9022ec-a068-4e93-b7d2-799dcd1ff1fd.jpeg</url>
      <title>Forem: Anay Nayak</title>
      <link>https://forem.com/anaynayak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/anaynayak"/>
    <language>en</language>
    <item>
      <title>Map Quiz: States of India</title>
      <dc:creator>Anay Nayak</dc:creator>
      <pubDate>Sun, 10 Jan 2021 07:43:03 +0000</pubDate>
      <link>https://forem.com/anaynayak/map-quiz-states-of-india-1330</link>
      <guid>https://forem.com/anaynayak/map-quiz-states-of-india-1330</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;A Map quiz for identifying states of India built primarily for the &lt;a href="https://en.wikipedia.org/wiki/10-foot_user_interface"&gt;10 foot user experience&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Category Submission:
&lt;/h3&gt;

&lt;p&gt;Random Roulette&lt;/p&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://maps-quiz-s79oh.ondigitalocean.app/"&gt;https://maps-quiz-s79oh.ondigitalocean.app/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YxqrPayO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vasbr9ck5ikpajadec0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YxqrPayO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vasbr9ck5ikpajadec0e.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;Provides a simple quiz for identifying various states of a country. By default it shows the one for India (see background section below)&lt;/p&gt;

&lt;p&gt;I intend to add support for other countries and some work for this already available locally by accessing urls like &lt;a href="http://localhost:3000/USA"&gt;http://localhost:3000/USA&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/anaynayak/maps-quiz"&gt;https://github.com/anaynayak/maps-quiz&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;MIT&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;With an ongoing pandemic, and my son's recent interest in a similar Geography quiz app, I wanted something that could help him get introduced to the various states of India. &lt;/p&gt;

&lt;p&gt;I wanted something that we could put on a Fire TV Stick and also improve his understanding of Geography over time. It isn't fully ready but something that I could hack together quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it
&lt;/h3&gt;

&lt;p&gt;I've used DigitalOcean before but the App Platform was new. Was happy to see a seamless experience to deploy a static website to production. &lt;/p&gt;

&lt;p&gt;I wanted to build something in React since it is also something that I now use at work. The 10 foot experience introduces some new challenges but was made much more simpler thanks to all the OSS products out there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built using this &lt;a href="https://github.com/bobinrinder/react-fire-tv-web-app-example"&gt;amazing template for building fire tv apps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/mtraynham/gadm-topo"&gt;https://github.com/mtraynham/gadm-topo&lt;/a&gt; for all the topojsons.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dohackathon</category>
    </item>
    <item>
      <title>A GitHub Action to find dead code using Vulture</title>
      <dc:creator>Anay Nayak</dc:creator>
      <pubDate>Fri, 28 Aug 2020 16:54:59 +0000</pubDate>
      <link>https://forem.com/anaynayak/a-github-action-to-find-dead-code-using-vulture-4ki7</link>
      <guid>https://forem.com/anaynayak/a-github-action-to-find-dead-code-using-vulture-4ki7</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/vulture/"&gt;Vulture&lt;/a&gt; is an awesome static code analyzer which helps identify dead code in Python repositories. As a python project maintainer, it is useful to know if a new pull request has introduced any dead code.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://dev.to/devteam/announcing-the-github-actions-hackathon-on-dev-3ljn"&gt;GitHub Actions Hackathon on DEV&lt;/a&gt; was an opportunity to experiment with Github Actions and make it easier to find dead code. The Github Actions marketplace didn't have any existing actions for Vulture and so I decided to write one. &lt;/p&gt;

&lt;p&gt;Sample run: &lt;a href="https://github.com/anaynayak/python-vulture-action/actions/runs/227230739"&gt;https://github.com/anaynayak/python-vulture-action/actions/runs/227230739&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XVVZqn3i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m8vrdvgf2unl5312b19g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XVVZqn3i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m8vrdvgf2unl5312b19g.png" alt="Diff shown on a Pull request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have enabled it on one my other repositories &lt;a href="https://github.com/anaynayak/buildnotify/"&gt;BuildNotify&lt;/a&gt; and it helped me realise that I had introduced some dead code as well 😄&lt;/p&gt;

&lt;p&gt;Here is the link if you'd try it on your repository &lt;a href="https://github.com/marketplace/actions/python-vulture-action"&gt;Python Vulture Action&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Sample workflow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vulture&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scavenge&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;anaynayak/python-vulture-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vulture&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;vulture-args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src --min-confidence &lt;/span&gt;&lt;span class="m"&gt;90&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;
&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anaynayak"&gt;
        anaynayak
      &lt;/a&gt; / &lt;a href="https://github.com/anaynayak/python-vulture-action"&gt;
        python-vulture-action
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Run Vulture on your Python codebase to identify dead code.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Python Vulture Action&lt;/h1&gt;
&lt;p&gt;This action runs &lt;a href="https://pypi.org/project/vulture/" rel="nofollow"&gt;Vulture&lt;/a&gt; on your Python codebase.&lt;/p&gt;
&lt;h2&gt;
Inputs&lt;/h2&gt;
&lt;h3&gt;
&lt;code&gt;vulture-args&lt;/code&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Required&lt;/strong&gt; Arguments passed to the vulture cli.&lt;/p&gt;
&lt;h1&gt;
Usage&lt;/h1&gt;
&lt;div class="highlight highlight-source-yaml js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;on&lt;/span&gt;: &lt;span class="pl-s"&gt;[push]&lt;/span&gt;

&lt;span class="pl-ent"&gt;jobs&lt;/span&gt;:
  &lt;span class="pl-ent"&gt;build&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;runs-on&lt;/span&gt;: &lt;span class="pl-s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;vulture&lt;/span&gt;
    &lt;span class="pl-ent"&gt;steps&lt;/span&gt;:
      - &lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;Checkout&lt;/span&gt;
        &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/checkout@v2&lt;/span&gt;
      - &lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;Scavenge&lt;/span&gt;
        &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;anaynayak/python-vulture-action@v1&lt;/span&gt;
        &lt;span class="pl-ent"&gt;id&lt;/span&gt;: &lt;span class="pl-s"&gt;vulture&lt;/span&gt;
        &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
          &lt;span class="pl-ent"&gt;vulture-args&lt;/span&gt;: &lt;span class="pl-s"&gt;example --min-confidence 90&lt;/span&gt;
&lt;/pre&gt;

&lt;/div&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/anaynayak/python-vulture-action"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/anaynayak/buildnotify/"&gt;https://github.com/anaynayak/buildnotify/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pypi.org/project/vulture/"&gt;https://pypi.org/project/vulture/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;span&gt;cover photo by &lt;a href="https://unsplash.com/@cdr6934?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Chris Ried&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/code?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
      <category>github</category>
      <category>python</category>
    </item>
    <item>
      <title>Haskell : Parsing a log message</title>
      <dc:creator>Anay Nayak</dc:creator>
      <pubDate>Wed, 24 Jun 2020 08:05:29 +0000</pubDate>
      <link>https://forem.com/anaynayak/haskell-parsing-a-log-message-1290</link>
      <guid>https://forem.com/anaynayak/haskell-parsing-a-log-message-1290</guid>
      <description>&lt;p&gt;Week 2 of CIS194 has an interesting problem which deals with parsing log messages. A set of types are provided and we need to write a &lt;code&gt;parseMessage&lt;/code&gt; method which returns a &lt;code&gt;LogMessage&lt;/code&gt; from a &lt;code&gt;String&lt;/code&gt; parameter.&lt;/p&gt;

&lt;h5&gt;
  
  
  Provided types:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;MessageType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Info&lt;/span&gt;
                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Warning&lt;/span&gt;
                 &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;TimeStamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt; &lt;span class="kt"&gt;MessageType&lt;/span&gt; &lt;span class="kt"&gt;TimeStamp&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
                &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Unknown&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  Sample log file:
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I 11 Initiating self-destruct sequence
E 70 3 Way too many pickles
E 65 8 Bad pickle-flange interaction detected
W 5 Flange is due for a check-up
I 7 Out for lunch, back in two time steps
Bad message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The log structure is largely similar for all log lines except for Error where we also have an error code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;W 5 Flange is due for a check-up&lt;/code&gt; is parsed as a Warning message with timestamp=5 and the rest as the message.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;E 23 5 Flange is due for a check-up&lt;/code&gt; is parsed as a Error with code 23, timestamp=5 and the rest as the message.&lt;/p&gt;

&lt;p&gt;We parse the message as Unknown if any of the following hold true:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Timestamp is not an integer&lt;/li&gt;
&lt;li&gt;message starts with a symbol other than E/W/I &lt;/li&gt;
&lt;li&gt;E messages not followed by an integer code.&lt;/li&gt;
&lt;li&gt;The message structure doesn't match &lt;code&gt;&amp;lt;type&amp;gt; &amp;lt;ts&amp;gt; &amp;lt;msg&amp;gt;&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Attempt #1&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;parseMessage&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt;
&lt;span class="n"&gt;parseMessage&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;parseCode&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;messageType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt; &lt;span class="n"&gt;messageType&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;
        &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Unknown&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;

&lt;span class="n"&gt;parseCode&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;MessageType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;TimeStamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parseCode&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"E"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parseError&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toInt&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unwords&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parseCode&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"W"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="kt"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toInt&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unwords&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parseCode&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="kt"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toInt&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unwords&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parseCode&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unwords&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;parseError&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;MessageType&lt;/span&gt;
&lt;span class="n"&gt;parseError&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;fmap&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="n"&gt;toInt&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;

&lt;span class="n"&gt;toInt&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="n"&gt;toInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;readMaybe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The  parsing of timestamp can fail and so we use a &lt;code&gt;Maybe Int&lt;/code&gt; type to handle the absence of a meaningful timestamp. Same holds true for error code. &lt;/li&gt;
&lt;li&gt;We pattern match on the &lt;code&gt;parseCode&lt;/code&gt; response so that we can handle happy scenarios and fallback to Unknown for everything else.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Attempt #2&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;parseMessage&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt;
&lt;span class="n"&gt;parseMessage&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maybeMessagetype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parseType&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maybeTs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parseTs&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;
        &lt;span class="n"&gt;lm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;liftA3&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt; &lt;span class="n"&gt;maybeMessagetype&lt;/span&gt; &lt;span class="n"&gt;maybeTs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;unwords&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kr"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fromMaybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Unknown&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;lm&lt;/span&gt;

&lt;span class="n"&gt;parseType&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;MessageType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;parseType&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="kt"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parseType&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"W"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="kt"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parseType&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"E"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readMaybe&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parseType&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Nothing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;parseTs&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;TimeStamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;parseTs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readMaybe&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In Attempt #1, we looked at the entire log message within the &lt;code&gt;parseCode&lt;/code&gt; method so that the structure was visible. However this doesn't scale that well. Instead, we change the structure so that each method handles a subset of the string and returns a &lt;code&gt;Maybe&lt;/code&gt; along with the string that wasn't consumed.&lt;/p&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;parseType and parseTs are only responsible for handling the bits that they understand. If it can't process the string, it returns a tuple with &lt;code&gt;Nothing&lt;/code&gt; and the original string.&lt;/li&gt;
&lt;li&gt;the parseMessage method needs to pass through left over state to the subsequent parseXYZ method.&lt;/li&gt;
&lt;li&gt;We combine all the Just values into a LogMessage by using liftA3.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Week 10 introduces us to a &lt;code&gt;Parser&lt;/code&gt; type:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;newtype Parser a = Parser { runParser :: String -&amp;gt; Maybe (a, String) }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The method signature in the previous solution looks very similar to a Parser.&lt;/p&gt;

&lt;p&gt;The Parser type lets you define parsers such as:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;satisfy&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Char&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Parser&lt;/span&gt; &lt;span class="kt"&gt;Char&lt;/span&gt;
&lt;span class="n"&gt;satisfy&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Parser&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
  &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;otherwise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;How do you use it ? For e.g. &lt;code&gt;char c = satisfy (== c)&lt;/code&gt; defines an exact match character parser. Similarly we can define a parser for other smaller units and compose them.&lt;/p&gt;

&lt;p&gt;Attempt #3&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;parseMessage&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt;
&lt;span class="n"&gt;parseMessage&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fromJust&lt;/span&gt;  &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;runLogMessageParser&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;runLogMessageParser&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fst&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;runParser&lt;/span&gt; &lt;span class="n"&gt;logMessage&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
    &lt;span class="n"&gt;logMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parseError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parseInfo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parseWarn&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parseUnknown&lt;/span&gt;
    &lt;span class="n"&gt;parseUnknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="kt"&gt;Unknown&lt;/span&gt; &lt;span class="n"&gt;parseMsg&lt;/span&gt;
    &lt;span class="n"&gt;parseError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;liftA3&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt; &lt;span class="n"&gt;parseECode&lt;/span&gt; &lt;span class="n"&gt;parseTs&lt;/span&gt; &lt;span class="n"&gt;parseMsg&lt;/span&gt;
    &lt;span class="n"&gt;parseInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;liftA3&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt; &lt;span class="n"&gt;parseICode&lt;/span&gt; &lt;span class="n"&gt;parseTs&lt;/span&gt; &lt;span class="n"&gt;parseMsg&lt;/span&gt;
    &lt;span class="n"&gt;parseWarn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;liftA3&lt;/span&gt; &lt;span class="kt"&gt;LogMessage&lt;/span&gt; &lt;span class="n"&gt;parseWCode&lt;/span&gt; &lt;span class="n"&gt;parseTs&lt;/span&gt; &lt;span class="n"&gt;parseMsg&lt;/span&gt;
    &lt;span class="n"&gt;parseECode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;fromInteger&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="sc"&gt;'E'&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;posInt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parseICode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="sc"&gt;'I'&lt;/span&gt; &lt;span class="o"&gt;$&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Info&lt;/span&gt;
    &lt;span class="n"&gt;parseWCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="sc"&gt;'W'&lt;/span&gt; &lt;span class="o"&gt;$&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Warning&lt;/span&gt;
    &lt;span class="n"&gt;parseTs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fromInteger&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;posInt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parseMsg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;many&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;satisfy&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Notes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We use &lt;code&gt;Alternative&lt;/code&gt; to make the various possibilities clear. &lt;code&gt;logMessage = parseError &amp;lt;|&amp;gt; parseInfo &amp;lt;|&amp;gt; parseWarn &amp;lt;|&amp;gt; parseUnknown&lt;/code&gt; tells us that we can expect only one of those four. &lt;/li&gt;
&lt;li&gt;We can compose small and well defined parsers so that the code is much more readable and expresses the state clearly. Unlike the previous attempt, we no longer have to explicitly pass the leftover string.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some symbols from the previous block:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Approach 3 doesn't show all the underlying constructs required to get the solution working. See the &lt;a href="https://gist.github.com/anaynayak/fd93e44d9953a7d2516e77e804cc7136#file-loganalysisv3full-hs"&gt;full solution&lt;/a&gt; for all that. There are a lot of concepts like Functor, Applicative and Alternatives which help bring clarity in the final solution.&lt;/p&gt;

&lt;p&gt;You can also experiment with the various solutions using repl.it &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@anaynayak/LogMessage?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



</description>
      <category>haskell</category>
    </item>
  </channel>
</rss>
