<story><title>Show HN: I built a poker site with Haskell</title><url>https://github.com/therewillbecode/haskell-poker</url></story><parent_chain><item><author>daenz</author><text>Haskell is dense.  I&amp;#x27;m picking it up now[0], so this project was very useful for me to see how some &amp;quot;real world&amp;quot; Haskell is written.  But yes, take for example this function&lt;p&gt;&lt;pre&gt;&lt;code&gt;  getSocketAPIPort :: Int -&amp;gt; IO Int
  getSocketAPIPort defaultPort = do
    maybeEnvPort &amp;lt;- lookupEnv &amp;quot;socketPort&amp;quot;
    case maybeEnvPort of
      Nothing   -&amp;gt; return defaultPort
      Just port -&amp;gt; maybe (return defaultPort) return (readMaybe port)
&lt;/code&gt;&lt;/pre&gt;
It gets a port from an environment variable, if it can, otherwise a default port.  Conceptually, this is easy to understand, but translating your understanding of that process to Haskell is not 1 to 1.  For example, the last line alone:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  Just port -&amp;gt; maybe (return defaultPort) return (readMaybe port)
&lt;/code&gt;&lt;/pre&gt;
You have to understand Maybe (and failure contexts), you have to understand that &amp;quot;return&amp;quot; does not return from a function like typical imperative languages, instead it wraps a type in a Monad (in this case, the IO Monad), and you also have to understand that most of those things on that line, including the &amp;quot;return&amp;quot; function, are parameters to the &amp;quot;maybe&amp;quot; function.&lt;p&gt;There&amp;#x27;s a lot to understand in terms of the underlying machinery of Haskell to be able to read its cryptic flow and syntax.  But it is worth it imo.&lt;p&gt;0. &lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;learnyouahaskell.com&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;learnyouahaskell.com&lt;/a&gt;</text></item><item><author>w0utert</author><text>So, I know literally nothing about Haskell, and I would rate my knowledge of functional programming theory as &amp;#x27;beginner&amp;#x27; at best, but I still get baffled every time when reading Haskell code that implements anything other than something trivial like a fibonacci sequence. The poker server code looks extremely tidy and well engineered, so that can&amp;#x27;t be the problem, but to me it&amp;#x27;s utterly incomprehensible. It seems like every expression implements 20 different things at the same time, which makes it really hard to decode what is going on.&lt;p&gt;Is it just me, or is this typical for all non-trivial Haskell code? I don&amp;#x27;t have any problems interpreting e.g. Clojure, or Javascript written in a functional style for that matter, but Haskell...</text></item></parent_chain><comment><author>chowells</author><text>Ouch. That function is actually written in a pretty convoluted and redundant way.&lt;p&gt;&lt;pre&gt;&lt;code&gt;    getSocketAPIPort :: Int -&amp;gt; IO Int
    getSocketAPIPort defaultPort = do
        maybeEnvPort &amp;lt;- lookupEnv &amp;quot;socketPort&amp;quot;
        return . fromMaybe defaultPort $ maybeEnvPort &amp;gt;&amp;gt;= readMaybe
&lt;/code&gt;&lt;/pre&gt;
That&amp;#x27;s starting to border on over-terse, so you could expand the bind operator into do notation if you wanted to spread it out a bit further. On the other hand, it&amp;#x27;s also starting to feel over-verbose, using do notation for only a single IO action. Maybe...&lt;p&gt;&lt;pre&gt;&lt;code&gt;    getSocketAPIPort :: Int -&amp;gt; IO Int
    getSocketAPIPort defaultPort = fromMaybe defaultPort . (readMaybe =&amp;lt;&amp;lt;) &amp;lt;$&amp;gt; lookupEnv &amp;quot;socketPort&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
That might be going too far. But maybe it&amp;#x27;s what I&amp;#x27;d write. Just depends on how much I expect to make this more complicated in the future. This form has the simplest flow to read. I mean... it&amp;#x27;s dense. Really dense. But it has the fewest total things going on, and it neatly divides into three interesting parts, easily understood in isolation, plumbed together with two common combinators. But it&amp;#x27;s also pretty rigid in structure. If you ever want to add other sources for finding the port or change the priorities of them, that form would need to be totally rewritten, and probably would end up back in do notation.&lt;p&gt;But in every case, all the various return calls should be combined into one (or none, if you use fmap or &amp;lt;$&amp;gt;), and the fallback to the default should only be written once.</text></comment>
<story><title>Show HN: I built a poker site with Haskell</title><url>https://github.com/therewillbecode/haskell-poker</url></story><parent_chain><item><author>daenz</author><text>Haskell is dense.  I&amp;#x27;m picking it up now[0], so this project was very useful for me to see how some &amp;quot;real world&amp;quot; Haskell is written.  But yes, take for example this function&lt;p&gt;&lt;pre&gt;&lt;code&gt;  getSocketAPIPort :: Int -&amp;gt; IO Int
  getSocketAPIPort defaultPort = do
    maybeEnvPort &amp;lt;- lookupEnv &amp;quot;socketPort&amp;quot;
    case maybeEnvPort of
      Nothing   -&amp;gt; return defaultPort
      Just port -&amp;gt; maybe (return defaultPort) return (readMaybe port)
&lt;/code&gt;&lt;/pre&gt;
It gets a port from an environment variable, if it can, otherwise a default port.  Conceptually, this is easy to understand, but translating your understanding of that process to Haskell is not 1 to 1.  For example, the last line alone:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  Just port -&amp;gt; maybe (return defaultPort) return (readMaybe port)
&lt;/code&gt;&lt;/pre&gt;
You have to understand Maybe (and failure contexts), you have to understand that &amp;quot;return&amp;quot; does not return from a function like typical imperative languages, instead it wraps a type in a Monad (in this case, the IO Monad), and you also have to understand that most of those things on that line, including the &amp;quot;return&amp;quot; function, are parameters to the &amp;quot;maybe&amp;quot; function.&lt;p&gt;There&amp;#x27;s a lot to understand in terms of the underlying machinery of Haskell to be able to read its cryptic flow and syntax.  But it is worth it imo.&lt;p&gt;0. &lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;learnyouahaskell.com&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;learnyouahaskell.com&lt;/a&gt;</text></item><item><author>w0utert</author><text>So, I know literally nothing about Haskell, and I would rate my knowledge of functional programming theory as &amp;#x27;beginner&amp;#x27; at best, but I still get baffled every time when reading Haskell code that implements anything other than something trivial like a fibonacci sequence. The poker server code looks extremely tidy and well engineered, so that can&amp;#x27;t be the problem, but to me it&amp;#x27;s utterly incomprehensible. It seems like every expression implements 20 different things at the same time, which makes it really hard to decode what is going on.&lt;p&gt;Is it just me, or is this typical for all non-trivial Haskell code? I don&amp;#x27;t have any problems interpreting e.g. Clojure, or Javascript written in a functional style for that matter, but Haskell...</text></item></parent_chain><comment><author>mrkeen</author><text>If you&amp;#x27;ve wandered in from another language and are wondering what it might look like in a less terse language, here&amp;#x27;s an attempt:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    static IO&amp;lt;Integer&amp;gt; getSocketApiPort(@NotNull final Integer defaultPort) {
      return lookupEnv(&amp;quot;socketPort&amp;quot;)
        .flatMap((Optional&amp;lt;String&amp;gt; maybeEnvPort) -&amp;gt; {
          if(!maybeEnvPort.isPresent()) {
            return IO.of(defaultPort);
          } else {
            String strEnvPort = maybeEnvPort.get();
            Optional&amp;lt;Integer&amp;gt; envPort = readMaybe(strEnvPort);
            return IO.of(envPort.orElse(defaultPort));
          }
        });
    }&lt;/code&gt;&lt;/pre&gt;</text></comment>