Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  nodelist  faq  login

Would you people stop playing these stupid games?!?!?!!!!


programming / comp.lang.haskell / RE: Re: Mixing monads / binding

SubjectAuthor
* Mixing monads / bindingThoai Nguyen
+- Re: Mixing monads / bindingBenjamin Esham
`* Re: Mixing monads / bindingBarry Fishman
 `- Re: Mixing monads / bindingThoai Nguyen

1
Subject: Mixing monads / binding
From: Thoai Nguyen
Newsgroups: comp.lang.haskell
Organization: Newshosting.com - Highest quality at a great price! www.newshosting.com
Date: Tue, 6 Aug 2019 14:54 UTC
Path: i2pn2.org!i2pn.org!weretis.net!feeder7.news.weretis.net!newsreader4.netcologne.de!news.netcologne.de!peer01.ams1!peer.ams1.xlned.com!news.xlned.com!peer01.am4!peer.am4.highwinds-media.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx42.iad.POSTED!not-for-mail
Newsgroups: comp.lang.haskell
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
From: me...@thoaionline.com (Thoai Nguyen)
Subject: Mixing monads / binding
Lines: 25
Message-ID: <dwg2F.243764$Kf5.47661@fx42.iad>
X-Complaints-To: abuse(at)newshosting.com
NNTP-Posting-Date: Tue, 06 Aug 2019 14:54:01 UTC
Organization: Newshosting.com - Highest quality at a great price! www.newshosting.com
Date: Tue, 06 Aug 2019 14:54:01 GMT
X-Received-Bytes: 1548
X-Received-Body-CRC: 2478613129
View all headers
Hi fam,

This is a fairly noob question. Considering the following imaginary functions:

someCalculation :: String -> Maybe String
someCalculation = Just

main :: IO ()
main = getLine >>= someCalculation >>= putStrLn


What I want to do is to run a non-deterministic calculation on an input string, then print the output. In this case, 2 different monads are in use (Maybe & IO). Of course this wouldn't work due to incorrect typing.

What would be the right way to handle something like this in Haskell?

The someCalculation implementation is just a placeholder, but you get the idea...

Many thanks,


Subject: Re: Mixing monads / binding
From: Benjamin Esham
Newsgroups: comp.lang.haskell
Organization: United Federation of Planets
Date: Tue, 6 Aug 2019 19:37 UTC
References: 1
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail
From: use...@esham.io (Benjamin Esham)
Newsgroups: comp.lang.haskell
Subject: Re: Mixing monads / binding
Date: Tue, 6 Aug 2019 19:37:54 -0000 (UTC)
Organization: United Federation of Planets
Lines: 111
Message-ID: <jz06mssf.wyt3eh@bdesham.net>
References: <dwg2F.243764$Kf5.47661@fx42.iad>
Injection-Date: Tue, 6 Aug 2019 19:37:54 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="d5eb3651859b4f2f9400f9a692bc8d04";
logging-data="6943"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+oHIzIAEOaJNNq6jRDkktmDjteKlJQnxXTSnaRANRRfg=="
User-Agent: slrn/1.0.2 (Linux)
Cancel-Lock: sha1:XVSS3yMGcTMZCefEO7GoGlGM4aM=
View all headers
Thoai Nguyen wrote:

Hi fam,

This is a fairly noob question. Considering the following imaginary
functions:

someCalculation :: String -> Maybe String
someCalculation = Just

main :: IO ()
main = getLine >>= someCalculation >>= putStrLn

What I want to do is to run a non-deterministic calculation on an input
string, then print the output. In this case, 2 different monads are in use
(Maybe & IO). Of course this wouldn't work due to incorrect typing.

What would be the right way to handle something like this in Haskell?

The someCalculation implementation is just a placeholder, but you get the
idea...

In Haskell, any non-deterministic calculation is going to end up producing
an IO value, like IO String or IO (Maybe Int) or something like that. More
formally, people refer to this as "a value of type 'IO a'," where "a" is
what's called a "type variable." (In more complicated programs this often
ends up being somewhat obscured by a bunch of monad transformers that rest
on top of the IO monad, so the return value of an impure function might be
"AppT String" instead of "IO String", but under the covers the IO monad is
still involved.)

If your someCalculation function is impure, it needs to have a type more
like

    someCalculation :: String -> IO (Maybe String)

if it's possible for the function to fail in some way, or

    someCalculation :: String -> IO String

if not. It sounds to me as if your function can indeed fail, so I'll assume
that it's going to return an IO (Maybe String). If you haven't seen this
kind of notation before, it means "a String value that may or may not be
there, embedded within the IO monad." I recommend reading this kind of thing
from the inside out. Note that the type Maybe (IO String) is something
completely different (and I'm not sure I could even describe what it is...
I've never seen that kind of construction before, I don't think.)

A dummy implementation of the someCalculation function with this type
signature looks like

    someCalculation :: String -> IO (Maybe String)
    someCalculation = return . Just

or, equivalently,

    someCalculation :: String -> IO (Maybe String)
    someCalculation s = do
        return (Just s)

In either version, we first call "Just" on the input to convert it from a
String to a Maybe String. Next we call "return" on the Maybe String to
convert it to an IO (Maybe String).

As for how you'd actually use it, I'd recommend (at least for now) using
do-notation and pattern matching. Your main function as it exists now could
be rewritten

    main = do
        input <- getLine
        result <- someCalculation input
        putStrLn result

(although as you point out, this will be rejected by the compiler because
"someCalculation input" has the type Maybe String, not the type IO String
that you need in this context). With the new version of someCalculation,
your main function would become

    main = do
        input <- getLine
        maybeResult <- someCalculation input
        case maybeResult of
          Just result -> putStrLn result
          Nothing -> putStrLn "Oops, it didn't work!"

The case statement is what allows you to deal with the two possibilities for
"maybeResult": it's either "Just result" or else it's "Nothing". You can do
completely different things in the branches of the case statement, if you
want, but both branches must have the same type, and in this particular
situation that type must be IO (). This is also the return type of putStrLn,
so we're good there.

If you're in the kind of situation where, in the case of an error, you want
to just swap in a default value and continue on, you could use the
"fromMaybe" function:

    import Data.Maybe (fromMaybe)

    main = do
        input <- getLine
        maybeResult <- someCalculation input
        let result = fromMaybe "default value" maybeResult
        putStrLn result

Hope this helps,

Benjamin

--
Benjamin Esham
https://esham.io


Subject: Re: Mixing monads / binding
From: Barry Fishman
Newsgroups: comp.lang.haskell
Organization: Easynews - www.easynews.com
Date: Wed, 7 Aug 2019 13:30 UTC
References: 1
Path: i2pn2.org!i2pn.org!weretis.net!feeder7.news.weretis.net!newsreader4.netcologne.de!news.netcologne.de!peer01.ams1!peer.ams1.xlned.com!news.xlned.com!peer01.am4!peer.am4.highwinds-media.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx28.iad.POSTED!not-for-mail
From: bar...@ecubist.org (Barry Fishman)
Newsgroups: comp.lang.haskell
Subject: Re: Mixing monads / binding
References: <dwg2F.243764$Kf5.47661@fx42.iad>
Message-ID: <7nk1bp6r35.fsf@ecube.ecubist.org>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux)
Cancel-Lock: sha1:DbqgSRAYwIKvrf4m4KUg6vZTn94=
MIME-Version: 1.0
Content-Type: text/plain
Lines: 41
X-Complaints-To: abuse@easynews.com
Organization: Easynews - www.easynews.com
X-Complaints-Info: Please be sure to forward a copy of ALL headers otherwise we will be unable to process your complaint properly.
Date: Wed, 07 Aug 2019 09:30:06 -0400
X-Received-Bytes: 2199
X-Received-Body-CRC: 1668429014
View all headers

On 2019-08-06 14:54:01 +00, Thoai Nguyen wrote:
This is a fairly noob question. Considering the following imaginary functions:

someCalculation :: String -> Maybe String
someCalculation = Just

main :: IO ()
main = getLine >>= someCalculation >>= putStrLn


What I want to do is to run a non-deterministic calculation on an
input string, then print the output. In this case, 2 different monads
are in use (Maybe & IO). Of course this wouldn't work due to incorrect
typing.

What would be the right way to handle something like this in Haskell?

The someCalculation implementation is just a placeholder, but you get the idea...

The first >>= needs to have the same type of Monad on each side of it,
which you are not doing.  Also if you want to output the result though
putStrLn you need a function that converts you Maybe back to a String.

answerString :: Maybe String -> String
answerString = show

If you want to keep someCalculation free of the IO Monad you can nest
the Maybe inside the IO Monad:

 getLine >>= return . someCalculation >>= putStrLn . answerString

or:

 getLine >>= return . answerString . someCalculation >>= putStrLn

Note that any 'someCalculation >>= whatever' must return a Maybe, so you
can't go from 'Maybe a' to 'IO a' using just >>= operations.
--
Barry Fishman



Subject: RE: Re: Mixing monads / binding
From: Thoai Nguyen
Newsgroups: comp.lang.haskell
Organization: Newshosting.com - Highest quality at a great price! www.newshosting.com
Date: Wed, 7 Aug 2019 14:41 UTC
References: 1 2
Path: i2pn2.org!i2pn.org!weretis.net!feeder7.news.weretis.net!newsreader4.netcologne.de!news.netcologne.de!peer02.ams1!peer.ams1.xlned.com!news.xlned.com!peer02.fr7!futter-mich.highwinds-media.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!fx47.iad.POSTED!not-for-mail
Newsgroups: comp.lang.haskell
References: <dwg2F.243764$Kf5.47661@fx42.iad> <7nk1bp6r35.fsf@ecube.ecubist.org>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
From: me...@thoaionline.com (Thoai Nguyen)
Subject: RE: Re: Mixing monads / binding
Lines: 2
Message-ID: <5qB2F.223038$KQ6.218933@fx47.iad>
X-Complaints-To: abuse(at)newshosting.com
NNTP-Posting-Date: Wed, 07 Aug 2019 14:41:05 UTC
Organization: Newshosting.com - Highest quality at a great price! www.newshosting.com
Date: Wed, 07 Aug 2019 14:41:05 GMT
X-Received-Bytes: 950
X-Received-Body-CRC: 162345672
View all headers
Thanks for your help guys. I'm gonna go with Barry's implementation (convert and wrap Maybe into IO)


1
rocksolid light 0.7.2
clearneti2ptor