trace output statements

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

trace output statements

Damien Mattei-2
i have this function:

-- this function will return th N°BD from Sidonie for a given name
-- note: names have been standardized between Sidonie and WDS
getBD :: Connection -> String -> IO Float
getBD conn name = trace "Entering getBD" noBDfp
  where qry_head = "select `N° BD` from Coordonnées where Nom = ?" :: Query
        bd_rows :: IO [Only Text]
        bd_rows = query conn qry_head (Only (name::String))
--        noBDtxt :: [Text]
--        noBDtxt = fromOnly (Prelude.head bd_rows)
--        noBDtxt :: IO [Text]
--        lg = fmap Prelude.length bd_rows
--        lg2 = fmap show lg
        noBDtxt :: IO Text
--        noBDtxt = trace "lg " (fmap (fromOnly . Prelude.head) bd_rows)
        noBDtxt = trace "assigning noBDtxt" (fmap (fromOnly . Prelude.head) bd_rows)
--        noBDstr :: String
--        noBDstr = Text.unpack noBDtxt
        noBDstr :: IO String
        noBDstr = trace "assigning noBDstr" (fmap Text.unpack noBDtxt)
--        noBDfp = read $ noBDstr :: Float
        noBDfp :: IO Float
        noBDfp = fmap read noBDstr


call by :

let lstBD = Prelude.map (\elem ->
                                  getBD conn (Text.unpack (fst elem)))
                            rows

it works ok, in fact at some point it fails due to NULL sql value not again handle correctly , i have inserted trace statement that output variable, i understand it's not really good becaus it breaks the purity of haskell function, perheaps for this reason i have strange behavior of output:
...
Entering getBD
assigning noBDstr
assigning noBDtxt
Entering getBD
assigning noBDstr
assigning noBDtxt
Entering getBD
assigning noBDstr
assigning noBDtxt
*** Exception: UnexpectedNull {errSQLType = "VarString", errHaskellType = "Text", errFieldName = "N\194\176 BD", errMessage = "unexpected null in table Coordonn\195\169es of database sidonie"}
*Main>
you will notice noBDstr seems to be assigned before noBDtxt, but in the code i have the statements in this order:
        noBDtxt = trace "assigning noBDtxt" (fmap (fromOnly . Prelude.head) bd_rows)
        noBDstr :: IO String
        noBDstr = trace "assigning noBDstr" (fmap Text.unpack noBDtxt)

i just want to understand wht's happening, this is not critical for code as it works...
any idea?

Damien

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Tom Ellis-5
On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
> i have inserted trace statement that output variable
> ... i have strange behavior of output:

Let's take a simpler example.  Do you understand why the trace statments
from this small program appear in the order that they do?  (And for what
it's worth I really think you'll be better off writing programs using do
notation).


% cat test.hs
import Debug.Trace

result =
  let a = trace "evaluating a" 2
      b = trace "evaluating b" 10
      c = trace "evaluating c" (a + b)
  in c
~% ghci -e result test.hs
evaluating c
evaluating b
evaluating a
12
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Damien Mattei-2
lazyness....?

On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <[hidden email]> wrote:
On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
> i have inserted trace statement that output variable
> ... i have strange behavior of output:

Let's take a simpler example.  Do you understand why the trace statments
from this small program appear in the order that they do?  (And for what
it's worth I really think you'll be better off writing programs using do
notation).


% cat test.hs
import Debug.Trace

result =
  let a = trace "evaluating a" 2
      b = trace "evaluating b" 10
      c = trace "evaluating c" (a + b)
  in c
~% ghci -e result test.hs
evaluating c
evaluating b
evaluating a
12
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Tom Ellis-5
Yes, exactly!

On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien Mattei wrote:

> lazyness....?
>
> On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
> [hidden email]> wrote:
>
> > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
> > > i have inserted trace statement that output variable
> > > ... i have strange behavior of output:
> >
> > Let's take a simpler example.  Do you understand why the trace statments
> > from this small program appear in the order that they do?  (And for what
> > it's worth I really think you'll be better off writing programs using do
> > notation).
> >
> >
> > % cat test.hs
> > import Debug.Trace
> >
> > result =
> >   let a = trace "evaluating a" 2
> >       b = trace "evaluating b" 10
> >       c = trace "evaluating c" (a + b)
> >   in c
> > ~% ghci -e result test.hs
> > evaluating c
> > evaluating b
> > evaluating a
> > 12
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Damien Mattei-2
i will spent part of my christmas holidays, learning seriously Haskell...fonctor,monads,IO....
i hope next year i will ask less silly question ;-) in the haskell-cafe mailing list.
For now i'm sticked with problems with IO Monads,database IO, and i have to revamp all my code because it's not working as i want, having code in main is ok but if i put some part of code in a simple function it fails to compile or worse compile but ouput nothing or give/require  me /back IO * things  that are a nightmare to deal with...
i must admit i never has such difficulty learning a language... i think learning Monads from scratch again will help me, the frustrating part of all this is that i'm only trying to do database manipulation that would be easy in python or Scheme.
I do not want to blame myself more, i think that Haskell is too abstract for basic things such as IO, it's ok to be abstract for hard problems,C++ with standart template library for example but not for reading an input from a database and manipulate the data simply...

On Sun, Dec 23, 2018 at 4:11 PM Tom Ellis <[hidden email]> wrote:
Yes, exactly!

On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien Mattei wrote:
> lazyness....?
>
> On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
> [hidden email]> wrote:
>
> > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
> > > i have inserted trace statement that output variable
> > > ... i have strange behavior of output:
> >
> > Let's take a simpler example.  Do you understand why the trace statments
> > from this small program appear in the order that they do?  (And for what
> > it's worth I really think you'll be better off writing programs using do
> > notation).
> >
> >
> > % cat test.hs
> > import Debug.Trace
> >
> > result =
> >   let a = trace "evaluating a" 2
> >       b = trace "evaluating b" 10
> >       c = trace "evaluating c" (a + b)
> >   in c
> > ~% ghci -e result test.hs
> > evaluating c
> > evaluating b
> > evaluating a
> > 12
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Tom Ellis-5
I think forgetting about monads and just using do-notation will help you.

On Sun, Dec 23, 2018 at 04:44:57PM +0100, Damien Mattei wrote:

> i think learning Monads from scratch again will help me
>
> On Sun, Dec 23, 2018 at 4:11 PM Tom Ellis <
> [hidden email]> wrote:
>
> > Yes, exactly!
> >
> > On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien Mattei wrote:
> > > lazyness....?
> > >
> > > On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
> > > [hidden email]> wrote:
> > >
> > > > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
> > > > > i have inserted trace statement that output variable
> > > > > ... i have strange behavior of output:
> > > >
> > > > Let's take a simpler example.  Do you understand why the trace
> > statments
> > > > from this small program appear in the order that they do?  (And for
> > what
> > > > it's worth I really think you'll be better off writing programs using
> > do
> > > > notation).
> > > >
> > > >
> > > > % cat test.hs
> > > > import Debug.Trace
> > > >
> > > > result =
> > > >   let a = trace "evaluating a" 2
> > > >       b = trace "evaluating b" 10
> > > >       c = trace "evaluating c" (a + b)
> > > >   in c
> > > > ~% ghci -e result test.hs
> > > > evaluating c
> > > > evaluating b
> > > > evaluating a
> > > > 12
> > _______________________________________________
> > Haskell-Cafe mailing list
> > To (un)subscribe, modify options or view archives go to:
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> > Only members subscribed via the mailman list are allowed to post.

> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

erik
In reply to this post by Tom Ellis-5
Tom,

Why does "b" evaluate before "a" in your example? I would have thought left-hand and then right-hand if needed. I'm on my phone but I'd like to try the same example with booleans and `&&` instead of `+`.

Erik


On Sat, Dec 22, 2018, 11:40 PM Tom Ellis <[hidden email] wrote:
On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
> i have inserted trace statement that output variable
> ... i have strange behavior of output:

Let's take a simpler example.  Do you understand why the trace statments
from this small program appear in the order that they do?  (And for what
it's worth I really think you'll be better off writing programs using do
notation).


% cat test.hs
import Debug.Trace

result =
  let a = trace "evaluating a" 2
      b = trace "evaluating b" 10
      c = trace "evaluating c" (a + b)
  in c
~% ghci -e result test.hs
evaluating c
evaluating b
evaluating a
12
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Ian Denhardt
There are no guarantees about in what order these things will be
evaluated. The compiler is well within its rights to evaluate
the expressions in any order, or more than once even (though IIRC
ghc never does the latter). The left-to-right ordering holds for &&
because the Haskell report specifically defines[1] it as:

    True  && x       =  x
    False && _       =  False

In this case the compiler can't in general evaluate the RHS first,
because if the LHS is False and the RHS is bottom, this would be
incorrect. But this is due to the semantics of &&, and doesn't hold in
general.

-Ian

[1]: https://www.haskell.org/onlinereport/haskell2010/haskellch9.html#x16-1710009

Quoting erik (2018-12-23 15:19:04)

>    Tom,
>    Why does "b" evaluate before "a" in your example? I would have thought
>    left-hand and then right-hand if needed. I'm on my phone but I'd like
>    to try the same example with booleans and `&&` instead of `+`.
>    Erik
>    On Sat, Dec 22, 2018, 11:40 PM Tom Ellis
>    <[1][hidden email] wrote:
>
>      On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
>      > i have inserted trace statement that output variable
>      > ... i have strange behavior of output:
>      Let's take a simpler example.�  Do you understand why the trace
>      statments
>      from this small program appear in the order that they do?�  (And for
>      what
>      it's worth I really think you'll be better off writing programs
>      using do
>      notation).
>      % cat test.hs
>      import Debug.Trace
>      result =
>      �  let a = trace "evaluating a" 2
>      �  �  �  b = trace "evaluating b" 10
>      �  �  �  c = trace "evaluating c" (a + b)
>      �  in c
>      ~% ghci -e result test.hs
>      evaluating c
>      evaluating b
>      evaluating a
>      12
>      _______________________________________________
>      Haskell-Cafe mailing list
>      To (un)subscribe, modify options or view archives go to:
>      [2]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      Only members subscribed via the mailman list are allowed to post.
>
> Verweise
>
>    1. mailto:[hidden email]
>    2. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

erik
Ah, I see. I erroneously assumed binary operators would be defined in similar ways but I realize that's perhaps naive because with addition you're never not going to evaluate both sides, unlike with booleans.

That's interesting. Thanks for responding.

On Sun, Dec 23, 2018, 2:26 PM Ian Denhardt <[hidden email] wrote:
There are no guarantees about in what order these things will be
evaluated. The compiler is well within its rights to evaluate
the expressions in any order, or more than once even (though IIRC
ghc never does the latter). The left-to-right ordering holds for &&
because the Haskell report specifically defines[1] it as:

    True  && x       =  x
    False && _       =  False

In this case the compiler can't in general evaluate the RHS first,
because if the LHS is False and the RHS is bottom, this would be
incorrect. But this is due to the semantics of &&, and doesn't hold in
general.

-Ian

[1]: https://www.haskell.org/onlinereport/haskell2010/haskellch9.html#x16-1710009

Quoting erik (2018-12-23 15:19:04)
>    Tom,
>    Why does "b" evaluate before "a" in your example? I would have thought
>    left-hand and then right-hand if needed. I'm on my phone but I'd like
>    to try the same example with booleans and `&&` instead of `+`.
>    Erik
>    On Sat, Dec 22, 2018, 11:40 PM Tom Ellis
>    <[1][hidden email] wrote:
>
>      On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
>      > i have inserted trace statement that output variable
>      > ... i have strange behavior of output:
>      Let's take a simpler example.�  Do you understand why the trace
>      statments
>      from this small program appear in the order that they do?�  (And for
>      what
>      it's worth I really think you'll be better off writing programs
>      using do
>      notation).
>      % cat test.hs
>      import Debug.Trace
>      result =
>      �  let a = trace "evaluating a" 2
>      �  �  �  b = trace "evaluating b" 10
>      �  �  �  c = trace "evaluating c" (a + b)
>      �  in c
>      ~% ghci -e result test.hs
>      evaluating c
>      evaluating b
>      evaluating a
>      12
>      _______________________________________________
>      Haskell-Cafe mailing list
>      To (un)subscribe, modify options or view archives go to:
>      [2]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      Only members subscribed via the mailman list are allowed to post.
>
> Verweise
>
>    1. mailto:[hidden email]
>    2. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Damien Mattei-2
In reply to this post by Tom Ellis-5
yes i use do notation, but for example i have code that works in main and not in a function!

i print the code perheaps someone could help me:

first the function, so you have the import list too:

import Database.MySQL.Simple
import Database.MySQL.Simple.QueryResults
import Database.MySQL.Simple.Result

import Database.MySQL.Simple.QueryParams
import Database.MySQL.Simple.Param


import Control.Monad

import Data.Text as Text
--import Data.Int as Int
--import Data.List
import Debug.Trace
import Data.Maybe as Maybe


-- this function will return th N°BD from Sidonie for a given name
-- note: names have been standardized between Sidonie and WDS
getBD3 :: Connection -> String -> Float
getBD3 conn name = do
            let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where Nom = ?" :: Query
            (bd_rows :: [Only Text]) <- query conn qry_head_BD_Sidonie (Only (name::String))
            let noBDtxt = fromOnly (Prelude.head bd_rows) :: Text
            let noBDstr = Text.unpack noBDtxt :: String
            let noBDfp = read $ noBDstr :: Float
            return noBDfp


with this function i have this error:

Prelude> :load UpdateSidonie
[1 of 1] Compiling Main             ( UpdateSidonie.hs, interpreted )

UpdateSidonie.hs:54:13: error:
    • Couldn't match expected type ‘Float’ with actual type ‘IO Float’
    • In a stmt of a 'do' block:
        (bd_rows :: [Only Text]) <- query
                                      conn qry_head_BD_Sidonie (Only (name :: String))
      In the expression:
        do let qry_head_BD_Sidonie = ...
           (bd_rows :: [Only Text]) <- query
                                         conn qry_head_BD_Sidonie (Only (name :: String))
           let noBDtxt = ...
           let noBDstr = ...
           ....
      In an equation for ‘getBD3’:
          getBD3 conn name
            = do let qry_head_BD_Sidonie = ...
                 (bd_rows :: [Only Text]) <- query
                                               conn qry_head_BD_Sidonie (Only (name :: String))
                 let noBDtxt = ...
                 ....
   |
54 |             (bd_rows :: [Only Text]) <- query conn qry_head_BD_Sidonie (Only (name::String))
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.


i do not understand the error complaining that i return an IO float,because i'm sure it's a float in noBDfp

if i put the same lines of code in the main it works !!! :

main :: IO ()

main =

  do
    conn <- connect defaultConnectInfo
      { connectHost = "moita",
        connectUser = "mattei",
        connectPassword = "sidonie2",
        connectDatabase = "sidonie" }

 let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where Nom = ?" :: Query

 (bd_rows :: [Only Text]) <- query conn qry_head_BD_Sidonie (Only (name::String))

putStr "bd_rows ="
putStrLn $ show bd_rows

    let noBDtxt = fromOnly (Prelude.head bd_rows) :: Text

    let noBDstr = Text.unpack noBDtxt :: String
    let noBDfp = read $ noBDstr :: Float

    putStr "noBDfp ="
    (putStrLn (show noBDfp))


 close conn

it works i have output like this:

*Main> main
bd_rows =[Only {fromOnly = "-04.3982"}]
noBDtxt ="-04.3982"
noBDfp =-4.3982
noBDfp + 1 = -3.3982

i'm well getting a float in noBDfp , i even can add 1 to it :-) ( cool haskell...)

but i'm just wanting to that in the function getDB3 but it does not compile...

??????

Damien

On Sun, Dec 23, 2018 at 4:54 PM Tom Ellis <[hidden email]> wrote:
I think forgetting about monads and just using do-notation will help you.

On Sun, Dec 23, 2018 at 04:44:57PM +0100, Damien Mattei wrote:
> i think learning Monads from scratch again will help me
>
> On Sun, Dec 23, 2018 at 4:11 PM Tom Ellis <
> [hidden email]> wrote:
>
> > Yes, exactly!
> >
> > On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien Mattei wrote:
> > > lazyness....?
> > >
> > > On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
> > > [hidden email]> wrote:
> > >
> > > > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei wrote:
> > > > > i have inserted trace statement that output variable
> > > > > ... i have strange behavior of output:
> > > >
> > > > Let's take a simpler example.  Do you understand why the trace
> > statments
> > > > from this small program appear in the order that they do?  (And for
> > what
> > > > it's worth I really think you'll be better off writing programs using
> > do
> > > > notation).
> > > >
> > > >
> > > > % cat test.hs
> > > > import Debug.Trace
> > > >
> > > > result =
> > > >   let a = trace "evaluating a" 2
> > > >       b = trace "evaluating b" 10
> > > >       c = trace "evaluating c" (a + b)
> > > >   in c
> > > > ~% ghci -e result test.hs
> > > > evaluating c
> > > > evaluating b
> > > > evaluating a
> > > > 12
> > _______________________________________________
> > Haskell-Cafe mailing list
> > To (un)subscribe, modify options or view archives go to:
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> > Only members subscribed via the mailman list are allowed to post.

> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Ian Denhardt
The correct type annotation for getDB3 should be:

    getDB3 :: Connection -> String -> IO Float

Note the IO at the end. Functions in Haskell are just pure computation;
they can't have side effects -- so a function returning a Float can't
possibly talk to a database.

Instead, The type `IO a` represents a description of an action to
perform.  It's still just a value -- calling getDB3 doesn't *do*
anything. You can stitch these together using do-notation or functions
like >>=, and when the program is run the action defined by 'main' is
performed.

---

An analogy: you could imagine instead of IO we could give up, and write
code that computes a program in some other (imperative) programming
language) that we then hand off to an interpreter. For example, we could
compute a python program that counts from 1 to 99 like so:

    printNum :: Int -> String
    printNum n = "print('" ++ show n ++ "')\n"

    pythonProgram = concatMap printNum [1..99]

So we've defined a variable fullProgram that is a string with the source
code to a python program like:

    print('1')
    print('2')
    print('3')
    ...
    print('99')

..but we haven't actually run it. To do that we'd have to pass the
string off to the python interpreter.

This is a good way to think about what IO is -- main is like our
pythonProgram above, in that it is a description of actions to perform,
but *evaluating* it doesn't have any side effects -- it just computes
the description. When you run a Haskell program, this is like taking
the description defined by Main and passing it off to an interpreter.

---

So your definition of getDB3 is a description of actions to perform to
get a float from the database, but your type declaration says it's a
function that computes a float (without having to perform any
"actions").

This is a critical distinction that exists in Haskell but not most other
languages.

Hope this helps,

-Ian

Quoting Damien Mattei (2018-12-25 15:07:35)

>    yes i use do notation, but for example i have code that works in main
>    and not in a function!
>    i print the code perheaps someone could help me:
>    first the function, so you have the import list too:
>    import Database.MySQL.Simple
>    import Database.MySQL.Simple.QueryResults
>    import Database.MySQL.Simple.Result
>    import Database.MySQL.Simple.QueryParams
>    import Database.MySQL.Simple.Param
>    import Control.Monad
>    import Data.Text as Text
>    --import Data.Int as Int
>    --import Data.List
>    import Debug.Trace
>    import Data.Maybe as Maybe
>    -- this function will return th N°BD from Sidonie for a given name
>    -- note: names have been standardized between Sidonie and WDS
>    getBD3 :: Connection -> String -> Float
>    getBD3 conn name = do
>    � � � � � � � � � � �  let qry_head_BD_Sidonie = "select `N° BD` from
>    Coordonnées where Nom = ?" :: Query
>    � � � � � � � � � � �  (bd_rows :: [Only Text]) <- query conn
>    qry_head_BD_Sidonie (Only (name::String))
>    � � � � � � � � � � �  let noBDtxt = fromOnly (Prelude.head bd_rows) ::
>    Text
>    � � � � � � � � � � �  let noBDstr = Text.unpack noBDtxt :: String
>    � � � � � � � � � � �  let noBDfp = read $ noBDstr :: Float
>    � � � � � � � � � � �  return noBDfp
>    with this function i have this error:
>    Prelude> :load UpdateSidonie
>    [1 of 1] Compiling Main� � � � � � � � � � � �  ( UpdateSidonie.hs,
>    interpreted )
>    UpdateSidonie.hs:54:13: error:
>    � � �  � Couldn't match expected type �Float� with actual type �IO
>    Float�
>    � � �  � In a stmt of a 'do' block:
>    � � � � � � �  (bd_rows :: [Only Text]) <- query
>    � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
>     �  conn qry_head_BD_Sidonie (Only (name :: String))
>    � � � � �  In the expression:
>    � � � � � � �  do let qry_head_BD_Sidonie = ...
>    � � � � � � � � � �  (bd_rows :: [Only Text]) <- query
>    � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
>     � � � �  conn qry_head_BD_Sidonie (Only (name :: String))
>    � � � � � � � � � �  let noBDtxt = ...
>    � � � � � � � � � �  let noBDstr = ...
>    � � � � � � � � � �  ....
>    � � � � �  In an equation for �getBD3�:
>    � � � � � � � � �  getBD3 conn name
>    � � � � � � � � � � �  = do let qry_head_BD_Sidonie = ...
>    � � � � � � � � � � � � � � � �  (bd_rows :: [Only Text]) <- query
>    � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
>     � � � � � � � � � �  conn qry_head_BD_Sidonie (Only (name :: String))
>    � � � � � � � � � � � � � � � �  let noBDtxt = ...
>    � � � � � � � � � � � � � � � �  ....
>    � �  |
>    54 |� � � � � � � � � � � �  (bd_rows :: [Only Text]) <- query conn
>    qry_head_BD_Sidonie (Only (name::String))
>    � �  |� � � � � � � � � � � �
>    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>    ^^^^^^^^^
>    Failed, no modules loaded.
>    i do not understand the error complaining that i return an IO
>    float,because i'm sure it's a float in noBDfp
>    if i put the same lines of code in the main it works !!! :
>    main :: IO ()
>    main =
>    �  do
>    � � �  conn <- connect defaultConnectInfo
>    � � � � �  { connectHost = "moita",
>    � � � � � � �  connectUser = "mattei",
>    � � � � � � �  connectPassword = "sidonie2",
>    � � � � � � �  connectDatabase = "sidonie" }
>    � let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where
>    Nom = ?" :: Query
>    � (bd_rows :: [Only Text]) <- query conn qry_head_BD_Sidonie (Only
>    (name::String))
>    putStr "bd_rows ="
>    putStrLn $ show bd_rows
>    � � �  let noBDtxt = fromOnly (Prelude.head bd_rows) :: Text
>    � � �  let noBDstr = Text.unpack noBDtxt :: String
>    � � �  let noBDfp = read $ noBDstr :: Float
>    � � �  putStr "noBDfp ="
>    � � �  (putStrLn (show noBDfp))
>    � close conn
>    it works i have output like this:
>    *Main> main
>    bd_rows =[Only {fromOnly = "-04.3982"}]
>    noBDtxt ="-04.3982"
>    noBDfp =-4.3982
>    noBDfp + 1 = -3.3982
>    i'm well getting a float in noBDfp , i even can add 1 to it :-) ( cool
>    haskell...)
>    but i'm just wanting to that in the function getDB3 but it does not
>    compile...
>    ??????
>    Damien
>
>    On Sun, Dec 23, 2018 at 4:54 PM Tom Ellis
>    <[1][hidden email]> wrote:
>
>      I think forgetting about monads and just using do-notation will help
>      you.
>      On Sun, Dec 23, 2018 at 04:44:57PM +0100, Damien Mattei wrote:
>      > i think learning Monads from scratch again will help me
>      >
>      > On Sun, Dec 23, 2018 at 4:11 PM Tom Ellis <
>      > [2][hidden email]> wrote:
>      >
>      > > Yes, exactly!
>      > >
>      > > On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien Mattei wrote:
>      > > > lazyness....?
>      > > >
>      > > > On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
>      > > > [3][hidden email]> wrote:
>      > > >
>      > > > > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien Mattei
>      wrote:
>      > > > > > i have inserted trace statement that output variable
>      > > > > > ... i have strange behavior of output:
>      > > > >
>      > > > > Let's take a simpler example.�  Do you understand why the
>      trace
>      > > statments
>      > > > > from this small program appear in the order that they do?�
>      (And for
>      > > what
>      > > > > it's worth I really think you'll be better off writing
>      programs using
>      > > do
>      > > > > notation).
>      > > > >
>      > > > >
>      > > > > % cat test.hs
>      > > > > import Debug.Trace
>      > > > >
>      > > > > result =
>      > > > >�  � let a = trace "evaluating a" 2
>      > > > >�  �  �  � b = trace "evaluating b" 10
>      > > > >�  �  �  � c = trace "evaluating c" (a + b)
>      > > > >�  � in c
>      > > > > ~% ghci -e result test.hs
>      > > > > evaluating c
>      > > > > evaluating b
>      > > > > evaluating a
>      > > > > 12
>      > > _______________________________________________
>      > > Haskell-Cafe mailing list
>      > > To (un)subscribe, modify options or view archives go to:
>      > > [4]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      > > Only members subscribed via the mailman list are allowed to
>      post.
>      > _______________________________________________
>      > Haskell-Cafe mailing list
>      > To (un)subscribe, modify options or view archives go to:
>      > [5]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      > Only members subscribed via the mailman list are allowed to post.
>      _______________________________________________
>      Haskell-Cafe mailing list
>      To (un)subscribe, modify options or view archives go to:
>      [6]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      Only members subscribed via the mailman list are allowed to post.
>
> Verweise
>
>    1. mailto:[hidden email]
>    2. mailto:[hidden email]
>    3. mailto:[hidden email]
>    4. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    5. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    6. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Ian Denhardt

(Adding the list back to Cc; you forgot to hit reply all)

Quoting Damien Mattei (2018-12-25 16:57:04)

> i get in trouble understanding what fmap was doing,

fmap (for IO) just applies a function to the result of the action, so:

    fmap f action

is equivalent to:

    do
        result <- action
        return (f result)

> and why the same thing to do in main and in a function had so
> different implementations...

I suspect the modified version of the program has some differences that
aren't strictly necessary just to factor out the relevant bits into
their own definition; this *shouldn't* be major surgery. Hard for me to
point out without having the two full examples handy.

Quoting Damien Mattei (2018-12-25 16:57:04)

>    yes, i understand with your python example, it's like read on a web
>    page, IO are not a "cake" but IO are "a recipe for the cake"...
>    functions are pure in haskell, so they can not have side effects...
>    what put me some trouble is an answer 2 weeks ago, someone gave me
>    hints that lead to this solution for getDB:
>    getBD :: Connection -> String -> IO Float
>    getBD conn name = trace "Entering getBD" noBDfp
>    �  where qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where
>    Nom = ?" :: Query
>    � � � � � � �  bd_rows :: IO [Only Text]
>    � � � � � � �  bd_rows = query conn qry_head_BD_Sidonie (Only
>    (name::String))
>    � � � � � � �  noBDtxt :: IO Text
>    � � � � � � �  noBDtxt = trace "assigning noBDtxt" (fmap (fromOnly .
>    Prelude.head) bd_rows)
>    � � � � � � �  noBDstr :: IO String
>    � � � � � � �  noBDstr = trace "assigning noBDstr" (fmap Text.unpack
>    noBDtxt)
>    � � � � � � �  noBDfp :: IO Float
>    � � � � � � �  noBDfp = fmap read noBDstr
>    which was code different from the code in main,i get in trouble
>    understanding what fmap was doing , and why the same thing to do in
>    main and in a function had so different implementations...
>
>    On Tue, Dec 25, 2018 at 10:19 PM Ian Denhardt <[1][hidden email]>
>    wrote:
>
>      The correct type annotation for getDB3 should be:
>      �  �  getDB3 :: Connection -> String -> IO Float
>      Note the IO at the end. Functions in Haskell are just pure
>      computation;
>      they can't have side effects -- so a function returning a Float
>      can't
>      possibly talk to a database.
>      Instead, The type `IO a` represents a description of an action to
>      perform.�  It's still just a value -- calling getDB3 doesn't *do*
>      anything. You can stitch these together using do-notation or
>      functions
>      like >>=, and when the program is run the action defined by 'main'
>      is
>      performed.
>      ---
>      An analogy: you could imagine instead of IO we could give up, and
>      write
>      code that computes a program in some other (imperative) programming
>      language) that we then hand off to an interpreter. For example, we
>      could
>      compute a python program that counts from 1 to 99 like so:
>      �  �  printNum :: Int -> String
>      �  �  printNum n = "print('" ++ show n ++ "')\n"
>      �  �  pythonProgram = concatMap printNum [1..99]
>      So we've defined a variable fullProgram that is a string with the
>      source
>      code to a python program like:
>      �  �  print('1')
>      �  �  print('2')
>      �  �  print('3')
>      �  �  ...
>      �  �  print('99')
>      ..but we haven't actually run it. To do that we'd have to pass the
>      string off to the python interpreter.
>      This is a good way to think about what IO is -- main is like our
>      pythonProgram above, in that it is a description of actions to
>      perform,
>      but *evaluating* it doesn't have any side effects -- it just
>      computes
>      the description. When you run a Haskell program, this is like taking
>      the description defined by Main and passing it off to an
>      interpreter.
>      ---
>      So your definition of getDB3 is a description of actions to perform
>      to
>      get a float from the database, but your type declaration says it's a
>      function that computes a float (without having to perform any
>      "actions").
>      This is a critical distinction that exists in Haskell but not most
>      other
>      languages.
>      Hope this helps,
>      -Ian
>      Quoting Damien Mattei (2018-12-25 15:07:35)
>      >�  �  yes i use do notation, but for example i have code that works
>      in main
>      >�  �  and not in a function!
>      >�  �  i print the code perheaps someone could help me:
>      >�  �  first the function, so you have the import list too:
>      >�  �  import Database.MySQL.Simple
>      >�  �  import Database.MySQL.Simple.QueryResults
>      >�  �  import Database.MySQL.Simple.Result
>      >�  �  import Database.MySQL.Simple.QueryParams
>      >�  �  import Database.MySQL.Simple.Param
>      >�  �  import Control.Monad
>      >�  �  import Data.Text as Text
>      >�  �  --import Data.Int as Int
>      >�  �  --import Data.List
>      >�  �  import Debug.Trace
>      >�  �  import Data.Maybe as Maybe
>      >�  �  -- this function will return th N°BD from Sidonie for a
>      given name
>      >�  �  -- note: names have been standardized between Sidonie and WDS
>      >�  �  getBD3 :: Connection -> String -> Float
>      >�  �  getBD3 conn name = do
>      >�  �  � � � � � � � � � � ��  let
>      qry_head_BD_Sidonie = "select `N° BD` from
>      >�  �  Coordonnées where Nom = ?" :: Query
>      >�  �  � � � � � � � � � � ��  (bd_rows ::
>      [Only Text]) <- query conn
>      >�  �  qry_head_BD_Sidonie (Only (name::String))
>      >�  �  � � � � � � � � � � ��  let noBDtxt =
>      fromOnly (Prelude.head bd_rows) ::
>      >�  �  Text
>      >�  �  � � � � � � � � � � ��  let noBDstr =
>      Text.unpack noBDtxt :: String
>      >�  �  � � � � � � � � � � ��  let noBDfp =
>      read $ noBDstr :: Float
>      >�  �  � � � � � � � � � � ��  return noBDfp
>      >�  �  with this function i have this error:
>      >�  �  Prelude> :load UpdateSidonie
>      >�  �  [1 of 1] Compiling Main� � � � � � � � �
>      � � ��  ( UpdateSidonie.hs,
>      >�  �  interpreted )
>      >�  �  UpdateSidonie.hs:54:13: error:
>      >�  �  � � ��  � Couldn't match expected type �Float�
>      with actual type �IO
>      >�  �  Float�
>      >�  �  � � ��  � In a stmt of a 'do' block:
>      >�  �  � � � � � � ��  (bd_rows :: [Only Text]) <-
>      query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � ��  conn qry_head_BD_Sidonie (Only (name :: String))
>      >�  �  � � � � ��  In the expression:
>      >�  �  � � � � � � ��  do let qry_head_BD_Sidonie =
>      ...
>      >�  �  � � � � � � � � � ��  (bd_rows :: [Only
>      Text]) <- query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � � � � ��  conn qry_head_BD_Sidonie (Only (name ::
>      String))
>      >�  �  � � � � � � � � � ��  let noBDtxt = ...
>      >�  �  � � � � � � � � � ��  let noBDstr = ...
>      >�  �  � � � � � � � � � ��  ....
>      >�  �  � � � � ��  In an equation for �getBD3�:
>      >�  �  � � � � � � � � ��  getBD3 conn name
>      >�  �  � � � � � � � � � � ��  = do let
>      qry_head_BD_Sidonie = ...
>      >�  �  � � � � � � � � � � � � � � �
>      ��  (bd_rows :: [Only Text]) <- query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � � � � � � � � � � ��  conn
>      qry_head_BD_Sidonie (Only (name :: String))
>      >�  �  � � � � � � � � � � � � � � �
>      ��  let noBDtxt = ...
>      >�  �  � � � � � � � � � � � � � � �
>      ��  ....
>      >�  �  � ��  |
>      >�  �  54 |� � � � � � � � � � � ��
>      (bd_rows :: [Only Text]) <- query conn
>      >�  �  qry_head_BD_Sidonie (Only (name::String))
>      >�  �  � ��  |� � � � � � � � � � � �
>      >�  �
>      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>      ^^^
>      >�  �  ^^^^^^^^^
>      >�  �  Failed, no modules loaded.
>      >�  �  i do not understand the error complaining that i return an IO
>      >�  �  float,because i'm sure it's a float in noBDfp
>      >�  �  if i put the same lines of code in the main it works !!! :
>      >�  �  main :: IO ()
>      >�  �  main =
>      >�  �  ��  do
>      >�  �  � � ��  conn <- connect defaultConnectInfo
>      >�  �  � � � � ��  { connectHost = "moita",
>      >�  �  � � � � � � ��  connectUser = "mattei",
>      >�  �  � � � � � � ��  connectPassword = "sidonie2",
>      >�  �  � � � � � � ��  connectDatabase = "sidonie" }
>      >�  �  � let qry_head_BD_Sidonie = "select `N° BD` from
>      Coordonnées where
>      >�  �  Nom = ?" :: Query
>      >�  �  � (bd_rows :: [Only Text]) <- query conn
>      qry_head_BD_Sidonie (Only
>      >�  �  (name::String))
>      >�  �  putStr "bd_rows ="
>      >�  �  putStrLn $ show bd_rows
>      >�  �  � � ��  let noBDtxt = fromOnly (Prelude.head bd_rows)
>      :: Text
>      >�  �  � � ��  let noBDstr = Text.unpack noBDtxt :: String
>      >�  �  � � ��  let noBDfp = read $ noBDstr :: Float
>      >�  �  � � ��  putStr "noBDfp ="
>      >�  �  � � ��  (putStrLn (show noBDfp))
>      >�  �  � close conn
>      >�  �  it works i have output like this:
>      >�  �  *Main> main
>      >�  �  bd_rows =[Only {fromOnly = "-04.3982"}]
>      >�  �  noBDtxt ="-04.3982"
>      >�  �  noBDfp =-4.3982
>      >�  �  noBDfp + 1 = -3.3982
>      >�  �  i'm well getting a float in noBDfp , i even can add 1 to it
>      :-) ( cool
>      >�  �  haskell...)
>      >�  �  but i'm just wanting to that in the function getDB3 but it
>      does not
>      >�  �  compile...
>      >�  �  ??????
>      >�  �  Damien
>      >
>      >�  �  On Sun, Dec 23, 2018 at 4:54 PM Tom Ellis
>      >�  �  <[1][2][hidden email]> wrote:
>      >
>      >�  �  �  I think forgetting about monads and just using do-notation
>      will help
>      >�  �  �  you.
>      >�  �  �  On Sun, Dec 23, 2018 at 04:44:57PM +0100, Damien Mattei
>      wrote:
>      >�  �  �  > i think learning Monads from scratch again will help me
>      >�  �  �  >
>      >�  �  �  > On Sun, Dec 23, 2018 at 4:11 PM Tom Ellis <
>      >�  �  �  > [2][3][hidden email]>
>      wrote:
>      >�  �  �  >
>      >�  �  �  > > Yes, exactly!
>      >�  �  �  > >
>      >�  �  �  > > On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien
>      Mattei wrote:
>      >�  �  �  > > > lazyness....?
>      >�  �  �  > > >
>      >�  �  �  > > > On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
>      >�  �  �  > > > [3][4][hidden email]>
>      wrote:
>      >�  �  �  > > >
>      >�  �  �  > > > > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien
>      Mattei
>      >�  �  �  wrote:
>      >�  �  �  > > > > > i have inserted trace statement that output
>      variable
>      >�  �  �  > > > > > ... i have strange behavior of output:
>      >�  �  �  > > > >
>      >�  �  �  > > > > Let's take a simpler example.��  Do you
>      understand why the
>      >�  �  �  trace
>      >�  �  �  > > statments
>      >�  �  �  > > > > from this small program appear in the order that
>      they do?�
>      >�  �  �  (And for
>      >�  �  �  > > what
>      >�  �  �  > > > > it's worth I really think you'll be better off
>      writing
>      >�  �  �  programs using
>      >�  �  �  > > do
>      >�  �  �  > > > > notation).
>      >�  �  �  > > > >
>      >�  �  �  > > > >
>      >�  �  �  > > > > % cat test.hs
>      >�  �  �  > > > > import Debug.Trace
>      >�  �  �  > > > >
>      >�  �  �  > > > > result =
>      >�  �  �  > > > >��  � let a = trace "evaluating a" 2
>      >�  �  �  > > > >��  ��  ��  � b = trace "evaluating b" 10
>      >�  �  �  > > > >��  ��  ��  � c = trace "evaluating c" (a +
>      b)
>      >�  �  �  > > > >��  � in c
>      >�  �  �  > > > > ~% ghci -e result test.hs
>      >�  �  �  > > > > evaluating c
>      >�  �  �  > > > > evaluating b
>      >�  �  �  > > > > evaluating a
>      >�  �  �  > > > > 12
>      >�  �  �  > > _______________________________________________
>      >�  �  �  > > Haskell-Cafe mailing list
>      >�  �  �  > > To (un)subscribe, modify options or view archives go
>      to:
>      >�  �  �  > >
>      [4][5]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  > > Only members subscribed via the mailman list are
>      allowed to
>      >�  �  �  post.
>      >�  �  �  > _______________________________________________
>      >�  �  �  > Haskell-Cafe mailing list
>      >�  �  �  > To (un)subscribe, modify options or view archives go to:
>      >�  �  �  >
>      [5][6]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  > Only members subscribed via the mailman list are allowed
>      to post.
>      >�  �  �  _______________________________________________
>      >�  �  �  Haskell-Cafe mailing list
>      >�  �  �  To (un)subscribe, modify options or view archives go to:
>      >�  �  �
>      [6][7]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  Only members subscribed via the mailman list are allowed
>      to post.
>      >
>      > Verweise
>      >
>      >�  �  1. mailto:[8][hidden email]
>      >�  �  2. mailto:[9][hidden email]
>      >�  �  3. mailto:[10][hidden email]
>      >�  �  4.
>      [11]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  5.
>      [12]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  6.
>      [13]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>
> Verweise
>
>    1. mailto:[hidden email]
>    2. mailto:[hidden email]
>    3. mailto:[hidden email]
>    4. mailto:[hidden email]
>    5. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    6. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    7. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    8. mailto:[hidden email]
>    9. mailto:[hidden email]
>   10. mailto:[hidden email]
>   11. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>   12. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>   13. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: trace output statements

Damien Mattei-2
i'm learning fmap, but for now i want to convert the previous function:

getBD :: Connection -> String -> IO Float
getBD conn name = do
            let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where Nom = ?" :: Query
            (bd_rows :: [Only Text]) <- query conn qry_head_BD_Sidonie (Only (name::String))
            let noBDtxt = fromOnly (Prelude.head bd_rows) :: Text
            let noBDstr = Text.unpack noBDtxt :: String
            let noBDfp = read $ noBDstr :: Float
            return noBDfp

that works but fails in case of NULL in database,
i want the code to works also with NULL, detecting them with Nothing, and short circuit them with Maybe or something else, so i change the function definition to this type and here is the whole code:

getBD2 :: Connection -> String -> IO (Maybe Float)
getBD2 conn name = do
            let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where Nom = ?" :: Query
            (bd_rows :: [Only (Maybe Text)]) <- query conn qry_head_BD_Sidonie (Only (name::String))
            let noBDtxt = if (isNothing (fromOnly (Prelude.head bd_rows)))
                          then (return Nothing)
                          else (fromOnly (Prelude.head bd_rows) :: Maybe Text)
            let noBDstr = Text.unpack noBDtxt :: Maybe String
            let noBDfp = read $ noBDstr :: Maybe Float
            return noBDfp

unfortunately it fails to compile, something is wrong here:

Prelude Data.Maybe> :load UpdateSidonie
[1 of 1] Compiling Main             ( UpdateSidonie.hs, interpreted )

UpdateSidonie.hs:68:33: error:
    • Couldn't match type ‘Text’ with ‘Maybe a’
      Expected type: Maybe (Maybe a)
        Actual type: Maybe Text
    • In the expression:
        (fromOnly (Prelude.head bd_rows) :: Maybe Text)
      In the expression:
        if (isNothing (fromOnly (Prelude.head bd_rows))) then
            (return Nothing)
        else
            (fromOnly (Prelude.head bd_rows) :: Maybe Text)
      In an equation for ‘noBDtxt’:
          noBDtxt
            = if (isNothing (fromOnly (Prelude.head bd_rows))) then
                  (return Nothing)
              else
                  (fromOnly (Prelude.head bd_rows) :: Maybe Text)
    • Relevant bindings include
        noBDtxt :: Maybe (Maybe a) (bound at UpdateSidonie.hs:66:17)
   |
68 |                           else (fromOnly (Prelude.head bd_rows) :: Maybe Text)
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

UpdateSidonie.hs:69:27: error:
    • Couldn't match type ‘[Char]’ with ‘Maybe String’
      Expected type: Maybe String
        Actual type: String
    • In the expression: unpack noBDtxt :: Maybe String
      In an equation for ‘noBDstr’:
          noBDstr = unpack noBDtxt :: Maybe String
      In the expression:
        do let qry_head_BD_Sidonie = ...
           (bd_rows :: [Only (Maybe Text)]) <- query
                                                 conn qry_head_BD_Sidonie (Only (name :: String))
           let noBDtxt = ...
           let noBDstr = ...
           ....
   |
69 |             let noBDstr = Text.unpack noBDtxt :: Maybe String
   |                           ^^^^^^^^^^^^^^^^^^^

UpdateSidonie.hs:69:39: error:
    • Couldn't match expected type ‘Text’
                  with actual type ‘Maybe (Maybe a0)’
    • In the first argument of ‘unpack’, namely ‘noBDtxt’
      In the expression: unpack noBDtxt :: Maybe String
      In an equation for ‘noBDstr’:
          noBDstr = unpack noBDtxt :: Maybe String
   |
69 |             let noBDstr = Text.unpack noBDtxt :: Maybe String
   |                                       ^^^^^^^

UpdateSidonie.hs:70:33: error:
    • Couldn't match type ‘Maybe String’ with ‘[Char]’
      Expected type: String
        Actual type: Maybe String
    • In the second argument of ‘($)’, namely ‘noBDstr’
      In the expression: read $ noBDstr :: Maybe Float
      In an equation for ‘noBDfp’: noBDfp = read $ noBDstr :: Maybe Float
   |
70 |             let noBDfp = read $ noBDstr :: Maybe Float
   |                                 ^^^^^^^
Failed, no modules loaded.

what is the solution? it will help me in my project and to understand Haskell way of handling null objects.

Damien


On Tue, Dec 25, 2018 at 11:18 PM Ian Denhardt <[hidden email]> wrote:

(Adding the list back to Cc; you forgot to hit reply all)

Quoting Damien Mattei (2018-12-25 16:57:04)

> i get in trouble understanding what fmap was doing,

fmap (for IO) just applies a function to the result of the action, so:

    fmap f action

is equivalent to:

    do
        result <- action
        return (f result)

> and why the same thing to do in main and in a function had so
> different implementations...

I suspect the modified version of the program has some differences that
aren't strictly necessary just to factor out the relevant bits into
their own definition; this *shouldn't* be major surgery. Hard for me to
point out without having the two full examples handy.

Quoting Damien Mattei (2018-12-25 16:57:04)
>    yes, i understand with your python example, it's like read on a web
>    page, IO are not a "cake" but IO are "a recipe for the cake"...
>    functions are pure in haskell, so they can not have side effects...
>    what put me some trouble is an answer 2 weeks ago, someone gave me
>    hints that lead to this solution for getDB:
>    getBD :: Connection -> String -> IO Float
>    getBD conn name = trace "Entering getBD" noBDfp
>    �  where qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where
>    Nom = ?" :: Query
>    � � � � � � �  bd_rows :: IO [Only Text]
>    � � � � � � �  bd_rows = query conn qry_head_BD_Sidonie (Only
>    (name::String))
>    � � � � � � �  noBDtxt :: IO Text
>    � � � � � � �  noBDtxt = trace "assigning noBDtxt" (fmap (fromOnly .
>    Prelude.head) bd_rows)
>    � � � � � � �  noBDstr :: IO String
>    � � � � � � �  noBDstr = trace "assigning noBDstr" (fmap Text.unpack
>    noBDtxt)
>    � � � � � � �  noBDfp :: IO Float
>    � � � � � � �  noBDfp = fmap read noBDstr
>    which was code different from the code in main,i get in trouble
>    understanding what fmap was doing , and why the same thing to do in
>    main and in a function had so different implementations...
>
>    On Tue, Dec 25, 2018 at 10:19 PM Ian Denhardt <[1][hidden email]>
>    wrote:
>
>      The correct type annotation for getDB3 should be:
>      �  �  getDB3 :: Connection -> String -> IO Float
>      Note the IO at the end. Functions in Haskell are just pure
>      computation;
>      they can't have side effects -- so a function returning a Float
>      can't
>      possibly talk to a database.
>      Instead, The type `IO a` represents a description of an action to
>      perform.�  It's still just a value -- calling getDB3 doesn't *do*
>      anything. You can stitch these together using do-notation or
>      functions
>      like >>=, and when the program is run the action defined by 'main'
>      is
>      performed.
>      ---
>      An analogy: you could imagine instead of IO we could give up, and
>      write
>      code that computes a program in some other (imperative) programming
>      language) that we then hand off to an interpreter. For example, we
>      could
>      compute a python program that counts from 1 to 99 like so:
>      �  �  printNum :: Int -> String
>      �  �  printNum n = "print('" ++ show n ++ "')\n"
>      �  �  pythonProgram = concatMap printNum [1..99]
>      So we've defined a variable fullProgram that is a string with the
>      source
>      code to a python program like:
>      �  �  print('1')
>      �  �  print('2')
>      �  �  print('3')
>      �  �  ...
>      �  �  print('99')
>      ..but we haven't actually run it. To do that we'd have to pass the
>      string off to the python interpreter.
>      This is a good way to think about what IO is -- main is like our
>      pythonProgram above, in that it is a description of actions to
>      perform,
>      but *evaluating* it doesn't have any side effects -- it just
>      computes
>      the description. When you run a Haskell program, this is like taking
>      the description defined by Main and passing it off to an
>      interpreter.
>      ---
>      So your definition of getDB3 is a description of actions to perform
>      to
>      get a float from the database, but your type declaration says it's a
>      function that computes a float (without having to perform any
>      "actions").
>      This is a critical distinction that exists in Haskell but not most
>      other
>      languages.
>      Hope this helps,
>      -Ian
>      Quoting Damien Mattei (2018-12-25 15:07:35)
>      >�  �  yes i use do notation, but for example i have code that works
>      in main
>      >�  �  and not in a function!
>      >�  �  i print the code perheaps someone could help me:
>      >�  �  first the function, so you have the import list too:
>      >�  �  import Database.MySQL.Simple
>      >�  �  import Database.MySQL.Simple.QueryResults
>      >�  �  import Database.MySQL.Simple.Result
>      >�  �  import Database.MySQL.Simple.QueryParams
>      >�  �  import Database.MySQL.Simple.Param
>      >�  �  import Control.Monad
>      >�  �  import Data.Text as Text
>      >�  �  --import Data.Int as Int
>      >�  �  --import Data.List
>      >�  �  import Debug.Trace
>      >�  �  import Data.Maybe as Maybe
>      >�  �  -- this function will return th N°BD from Sidonie for a
>      given name
>      >�  �  -- note: names have been standardized between Sidonie and WDS
>      >�  �  getBD3 :: Connection -> String -> Float
>      >�  �  getBD3 conn name = do
>      >�  �  � � � � � � � � � � ��  let
>      qry_head_BD_Sidonie = "select `N° BD` from
>      >�  �  Coordonnées where Nom = ?" :: Query
>      >�  �  � � � � � � � � � � ��  (bd_rows ::
>      [Only Text]) <- query conn
>      >�  �  qry_head_BD_Sidonie (Only (name::String))
>      >�  �  � � � � � � � � � � ��  let noBDtxt =
>      fromOnly (Prelude.head bd_rows) ::
>      >�  �  Text
>      >�  �  � � � � � � � � � � ��  let noBDstr =
>      Text.unpack noBDtxt :: String
>      >�  �  � � � � � � � � � � ��  let noBDfp =
>      read $ noBDstr :: Float
>      >�  �  � � � � � � � � � � ��  return noBDfp
>      >�  �  with this function i have this error:
>      >�  �  Prelude> :load UpdateSidonie
>      >�  �  [1 of 1] Compiling Main� � � � � � � � �
>      � � ��  ( UpdateSidonie.hs,
>      >�  �  interpreted )
>      >�  �  UpdateSidonie.hs:54:13: error:
>      >�  �  � � ��  � Couldn't match expected type �Float�
>      with actual type �IO
>      >�  �  Float�
>      >�  �  � � ��  � In a stmt of a 'do' block:
>      >�  �  � � � � � � ��  (bd_rows :: [Only Text]) <-
>      query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � ��  conn qry_head_BD_Sidonie (Only (name :: String))
>      >�  �  � � � � ��  In the expression:
>      >�  �  � � � � � � ��  do let qry_head_BD_Sidonie =
>      ...
>      >�  �  � � � � � � � � � ��  (bd_rows :: [Only
>      Text]) <- query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � � � � ��  conn qry_head_BD_Sidonie (Only (name ::
>      String))
>      >�  �  � � � � � � � � � ��  let noBDtxt = ...
>      >�  �  � � � � � � � � � ��  let noBDstr = ...
>      >�  �  � � � � � � � � � ��  ....
>      >�  �  � � � � ��  In an equation for �getBD3�:
>      >�  �  � � � � � � � � ��  getBD3 conn name
>      >�  �  � � � � � � � � � � ��  = do let
>      qry_head_BD_Sidonie = ...
>      >�  �  � � � � � � � � � � � � � � �
>      ��  (bd_rows :: [Only Text]) <- query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � � � � � � � � � � ��  conn
>      qry_head_BD_Sidonie (Only (name :: String))
>      >�  �  � � � � � � � � � � � � � � �
>      ��  let noBDtxt = ...
>      >�  �  � � � � � � � � � � � � � � �
>      ��  ....
>      >�  �  � ��  |
>      >�  �  54 |� � � � � � � � � � � ��
>      (bd_rows :: [Only Text]) <- query conn
>      >�  �  qry_head_BD_Sidonie (Only (name::String))
>      >�  �  � ��  |� � � � � � � � � � � �
>      >�  �
>      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>      ^^^
>      >�  �  ^^^^^^^^^
>      >�  �  Failed, no modules loaded.
>      >�  �  i do not understand the error complaining that i return an IO
>      >�  �  float,because i'm sure it's a float in noBDfp
>      >�  �  if i put the same lines of code in the main it works !!! :
>      >�  �  main :: IO ()
>      >�  �  main =
>      >�  �  ��  do
>      >�  �  � � ��  conn <- connect defaultConnectInfo
>      >�  �  � � � � ��  { connectHost = "moita",
>      >�  �  � � � � � � ��  connectUser = "mattei",
>      >�  �  � � � � � � ��  connectPassword = "sidonie2",
>      >�  �  � � � � � � ��  connectDatabase = "sidonie" }
>      >�  �  � let qry_head_BD_Sidonie = "select `N° BD` from
>      Coordonnées where
>      >�  �  Nom = ?" :: Query
>      >�  �  � (bd_rows :: [Only Text]) <- query conn
>      qry_head_BD_Sidonie (Only
>      >�  �  (name::String))
>      >�  �  putStr "bd_rows ="
>      >�  �  putStrLn $ show bd_rows
>      >�  �  � � ��  let noBDtxt = fromOnly (Prelude.head bd_rows)
>      :: Text
>      >�  �  � � ��  let noBDstr = Text.unpack noBDtxt :: String
>      >�  �  � � ��  let noBDfp = read $ noBDstr :: Float
>      >�  �  � � ��  putStr "noBDfp ="
>      >�  �  � � ��  (putStrLn (show noBDfp))
>      >�  �  � close conn
>      >�  �  it works i have output like this:
>      >�  �  *Main> main
>      >�  �  bd_rows =[Only {fromOnly = "-04.3982"}]
>      >�  �  noBDtxt ="-04.3982"
>      >�  �  noBDfp =-4.3982
>      >�  �  noBDfp + 1 = -3.3982
>      >�  �  i'm well getting a float in noBDfp , i even can add 1 to it
>      :-) ( cool
>      >�  �  haskell...)
>      >�  �  but i'm just wanting to that in the function getDB3 but it
>      does not
>      >�  �  compile...
>      >�  �  ??????
>      >�  �  Damien
>      >
>      >�  �  On Sun, Dec 23, 2018 at 4:54 PM Tom Ellis
>      >�  �  <[1][2][hidden email]> wrote:
>      >
>      >�  �  �  I think forgetting about monads and just using do-notation
>      will help
>      >�  �  �  you.
>      >�  �  �  On Sun, Dec 23, 2018 at 04:44:57PM +0100, Damien Mattei
>      wrote:
>      >�  �  �  > i think learning Monads from scratch again will help me
>      >�  �  �  >
>      >�  �  �  > On Sun, Dec 23, 2018 at 4:11 PM Tom Ellis <
>      >�  �  �  > [2][3][hidden email]>
>      wrote:
>      >�  �  �  >
>      >�  �  �  > > Yes, exactly!
>      >�  �  �  > >
>      >�  �  �  > > On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien
>      Mattei wrote:
>      >�  �  �  > > > lazyness....?
>      >�  �  �  > > >
>      >�  �  �  > > > On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
>      >�  �  �  > > > [3][4][hidden email]>
>      wrote:
>      >�  �  �  > > >
>      >�  �  �  > > > > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien
>      Mattei
>      >�  �  �  wrote:
>      >�  �  �  > > > > > i have inserted trace statement that output
>      variable
>      >�  �  �  > > > > > ... i have strange behavior of output:
>      >�  �  �  > > > >
>      >�  �  �  > > > > Let's take a simpler example.��  Do you
>      understand why the
>      >�  �  �  trace
>      >�  �  �  > > statments
>      >�  �  �  > > > > from this small program appear in the order that
>      they do?�
>      >�  �  �  (And for
>      >�  �  �  > > what
>      >�  �  �  > > > > it's worth I really think you'll be better off
>      writing
>      >�  �  �  programs using
>      >�  �  �  > > do
>      >�  �  �  > > > > notation).
>      >�  �  �  > > > >
>      >�  �  �  > > > >
>      >�  �  �  > > > > % cat test.hs
>      >�  �  �  > > > > import Debug.Trace
>      >�  �  �  > > > >
>      >�  �  �  > > > > result =
>      >�  �  �  > > > >��  � let a = trace "evaluating a" 2
>      >�  �  �  > > > >��  ��  ��  � b = trace "evaluating b" 10
>      >�  �  �  > > > >��  ��  ��  � c = trace "evaluating c" (a +
>      b)
>      >�  �  �  > > > >��  � in c
>      >�  �  �  > > > > ~% ghci -e result test.hs
>      >�  �  �  > > > > evaluating c
>      >�  �  �  > > > > evaluating b
>      >�  �  �  > > > > evaluating a
>      >�  �  �  > > > > 12
>      >�  �  �  > > _______________________________________________
>      >�  �  �  > > Haskell-Cafe mailing list
>      >�  �  �  > > To (un)subscribe, modify options or view archives go
>      to:
>      >�  �  �  > >
>      [4][5]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  > > Only members subscribed via the mailman list are
>      allowed to
>      >�  �  �  post.
>      >�  �  �  > _______________________________________________
>      >�  �  �  > Haskell-Cafe mailing list
>      >�  �  �  > To (un)subscribe, modify options or view archives go to:
>      >�  �  �  >
>      [5][6]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  > Only members subscribed via the mailman list are allowed
>      to post.
>      >�  �  �  _______________________________________________
>      >�  �  �  Haskell-Cafe mailing list
>      >�  �  �  To (un)subscribe, modify options or view archives go to:
>      >�  �  �
>      [6][7]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  Only members subscribed via the mailman list are allowed
>      to post.
>      >
>      > Verweise
>      >
>      >�  �  1. mailto:[8][hidden email]
>      >�  �  2. mailto:[9][hidden email]
>      >�  �  3. mailto:[10][hidden email]
>      >�  �  4.
>      [11]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  5.
>      [12]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  6.
>      [13]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>
> Verweise
>
>    1. mailto:[hidden email]
>    2. mailto:[hidden email]
>    3. mailto:[hidden email]
>    4. mailto:[hidden email]
>    5. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    6. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    7. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    8. mailto:[hidden email]
>    9. mailto:[hidden email]
>   10. mailto:[hidden email]
>   11. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>   12. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>   13. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Handling NULL value , was :trace output statements

Damien Mattei-2
finally, late in night i got myself a working solution :-) :
getBD2 :: Connection -> String -> IO (Maybe Float)
getBD2 conn name = do
            let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where Nom = ?" :: Query
            (bd_rows :: [Only (Maybe Text)]) <- query conn qry_head_BD_Sidonie (Only (name::String))
            let noBDtxt = fromOnly (Prelude.head bd_rows) :: Maybe Text
            case noBDtxt of
                 Nothing -> return Nothing
                 Just noBDtxt -> do
                                   putStrLn "getBD2"
                                   let noBDstr = Text.unpack noBDtxt :: String
                                   let noBDfp = readMaybe noBDstr :: Maybe Float
                                   return noBDfp

note that i had to change read in readMaybe due to Exception: Prelude.read: no parse,solved here (i do not really understand why) :

note also in the last lines i infer a Maybe Float from a NOT maybe String , but the compiler did not notice it....

in my main function i call and display like that:(2 solution due to a Just appearing in terminal...)

 noBD <- getBD2 conn name
    putStrLn ("noBD = " ++ (show noBD))
    putStrLn $ "noBD = " ++ maybe "NULL" show noBD

display like this:

getBD2
noBD = Just (-4.3982)
noBD = -4.3982

but if someone has a more elegant or concise solution ? ....

my opinion: Haskell is weird... :-)


On Wed, Dec 26, 2018 at 11:24 PM Damien Mattei <[hidden email]> wrote:
i'm learning fmap, but for now i want to convert the previous function:

getBD :: Connection -> String -> IO Float
getBD conn name = do
            let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where Nom = ?" :: Query
            (bd_rows :: [Only Text]) <- query conn qry_head_BD_Sidonie (Only (name::String))
            let noBDtxt = fromOnly (Prelude.head bd_rows) :: Text
            let noBDstr = Text.unpack noBDtxt :: String
            let noBDfp = read $ noBDstr :: Float
            return noBDfp

that works but fails in case of NULL in database,
i want the code to works also with NULL, detecting them with Nothing, and short circuit them with Maybe or something else, so i change the function definition to this type and here is the whole code:

getBD2 :: Connection -> String -> IO (Maybe Float)
getBD2 conn name = do
            let qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where Nom = ?" :: Query
            (bd_rows :: [Only (Maybe Text)]) <- query conn qry_head_BD_Sidonie (Only (name::String))
            let noBDtxt = if (isNothing (fromOnly (Prelude.head bd_rows)))
                          then (return Nothing)
                          else (fromOnly (Prelude.head bd_rows) :: Maybe Text)
            let noBDstr = Text.unpack noBDtxt :: Maybe String
            let noBDfp = read $ noBDstr :: Maybe Float
            return noBDfp

unfortunately it fails to compile, something is wrong here:

Prelude Data.Maybe> :load UpdateSidonie
[1 of 1] Compiling Main             ( UpdateSidonie.hs, interpreted )

UpdateSidonie.hs:68:33: error:
    • Couldn't match type ‘Text’ with ‘Maybe a’
      Expected type: Maybe (Maybe a)
        Actual type: Maybe Text
    • In the expression:
        (fromOnly (Prelude.head bd_rows) :: Maybe Text)
      In the expression:
        if (isNothing (fromOnly (Prelude.head bd_rows))) then
            (return Nothing)
        else
            (fromOnly (Prelude.head bd_rows) :: Maybe Text)
      In an equation for ‘noBDtxt’:
          noBDtxt
            = if (isNothing (fromOnly (Prelude.head bd_rows))) then
                  (return Nothing)
              else
                  (fromOnly (Prelude.head bd_rows) :: Maybe Text)
    • Relevant bindings include
        noBDtxt :: Maybe (Maybe a) (bound at UpdateSidonie.hs:66:17)
   |
68 |                           else (fromOnly (Prelude.head bd_rows) :: Maybe Text)
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

UpdateSidonie.hs:69:27: error:
    • Couldn't match type ‘[Char]’ with ‘Maybe String’
      Expected type: Maybe String
        Actual type: String
    • In the expression: unpack noBDtxt :: Maybe String
      In an equation for ‘noBDstr’:
          noBDstr = unpack noBDtxt :: Maybe String
      In the expression:
        do let qry_head_BD_Sidonie = ...
           (bd_rows :: [Only (Maybe Text)]) <- query
                                                 conn qry_head_BD_Sidonie (Only (name :: String))
           let noBDtxt = ...
           let noBDstr = ...
           ....
   |
69 |             let noBDstr = Text.unpack noBDtxt :: Maybe String
   |                           ^^^^^^^^^^^^^^^^^^^

UpdateSidonie.hs:69:39: error:
    • Couldn't match expected type ‘Text’
                  with actual type ‘Maybe (Maybe a0)’
    • In the first argument of ‘unpack’, namely ‘noBDtxt’
      In the expression: unpack noBDtxt :: Maybe String
      In an equation for ‘noBDstr’:
          noBDstr = unpack noBDtxt :: Maybe String
   |
69 |             let noBDstr = Text.unpack noBDtxt :: Maybe String
   |                                       ^^^^^^^

UpdateSidonie.hs:70:33: error:
    • Couldn't match type ‘Maybe String’ with ‘[Char]’
      Expected type: String
        Actual type: Maybe String
    • In the second argument of ‘($)’, namely ‘noBDstr’
      In the expression: read $ noBDstr :: Maybe Float
      In an equation for ‘noBDfp’: noBDfp = read $ noBDstr :: Maybe Float
   |
70 |             let noBDfp = read $ noBDstr :: Maybe Float
   |                                 ^^^^^^^
Failed, no modules loaded.

what is the solution? it will help me in my project and to understand Haskell way of handling null objects.

Damien


On Tue, Dec 25, 2018 at 11:18 PM Ian Denhardt <[hidden email]> wrote:

(Adding the list back to Cc; you forgot to hit reply all)

Quoting Damien Mattei (2018-12-25 16:57:04)

> i get in trouble understanding what fmap was doing,

fmap (for IO) just applies a function to the result of the action, so:

    fmap f action

is equivalent to:

    do
        result <- action
        return (f result)

> and why the same thing to do in main and in a function had so
> different implementations...

I suspect the modified version of the program has some differences that
aren't strictly necessary just to factor out the relevant bits into
their own definition; this *shouldn't* be major surgery. Hard for me to
point out without having the two full examples handy.

Quoting Damien Mattei (2018-12-25 16:57:04)
>    yes, i understand with your python example, it's like read on a web
>    page, IO are not a "cake" but IO are "a recipe for the cake"...
>    functions are pure in haskell, so they can not have side effects...
>    what put me some trouble is an answer 2 weeks ago, someone gave me
>    hints that lead to this solution for getDB:
>    getBD :: Connection -> String -> IO Float
>    getBD conn name = trace "Entering getBD" noBDfp
>    �  where qry_head_BD_Sidonie = "select `N° BD` from Coordonnées where
>    Nom = ?" :: Query
>    � � � � � � �  bd_rows :: IO [Only Text]
>    � � � � � � �  bd_rows = query conn qry_head_BD_Sidonie (Only
>    (name::String))
>    � � � � � � �  noBDtxt :: IO Text
>    � � � � � � �  noBDtxt = trace "assigning noBDtxt" (fmap (fromOnly .
>    Prelude.head) bd_rows)
>    � � � � � � �  noBDstr :: IO String
>    � � � � � � �  noBDstr = trace "assigning noBDstr" (fmap Text.unpack
>    noBDtxt)
>    � � � � � � �  noBDfp :: IO Float
>    � � � � � � �  noBDfp = fmap read noBDstr
>    which was code different from the code in main,i get in trouble
>    understanding what fmap was doing , and why the same thing to do in
>    main and in a function had so different implementations...
>
>    On Tue, Dec 25, 2018 at 10:19 PM Ian Denhardt <[1][hidden email]>
>    wrote:
>
>      The correct type annotation for getDB3 should be:
>      �  �  getDB3 :: Connection -> String -> IO Float
>      Note the IO at the end. Functions in Haskell are just pure
>      computation;
>      they can't have side effects -- so a function returning a Float
>      can't
>      possibly talk to a database.
>      Instead, The type `IO a` represents a description of an action to
>      perform.�  It's still just a value -- calling getDB3 doesn't *do*
>      anything. You can stitch these together using do-notation or
>      functions
>      like >>=, and when the program is run the action defined by 'main'
>      is
>      performed.
>      ---
>      An analogy: you could imagine instead of IO we could give up, and
>      write
>      code that computes a program in some other (imperative) programming
>      language) that we then hand off to an interpreter. For example, we
>      could
>      compute a python program that counts from 1 to 99 like so:
>      �  �  printNum :: Int -> String
>      �  �  printNum n = "print('" ++ show n ++ "')\n"
>      �  �  pythonProgram = concatMap printNum [1..99]
>      So we've defined a variable fullProgram that is a string with the
>      source
>      code to a python program like:
>      �  �  print('1')
>      �  �  print('2')
>      �  �  print('3')
>      �  �  ...
>      �  �  print('99')
>      ..but we haven't actually run it. To do that we'd have to pass the
>      string off to the python interpreter.
>      This is a good way to think about what IO is -- main is like our
>      pythonProgram above, in that it is a description of actions to
>      perform,
>      but *evaluating* it doesn't have any side effects -- it just
>      computes
>      the description. When you run a Haskell program, this is like taking
>      the description defined by Main and passing it off to an
>      interpreter.
>      ---
>      So your definition of getDB3 is a description of actions to perform
>      to
>      get a float from the database, but your type declaration says it's a
>      function that computes a float (without having to perform any
>      "actions").
>      This is a critical distinction that exists in Haskell but not most
>      other
>      languages.
>      Hope this helps,
>      -Ian
>      Quoting Damien Mattei (2018-12-25 15:07:35)
>      >�  �  yes i use do notation, but for example i have code that works
>      in main
>      >�  �  and not in a function!
>      >�  �  i print the code perheaps someone could help me:
>      >�  �  first the function, so you have the import list too:
>      >�  �  import Database.MySQL.Simple
>      >�  �  import Database.MySQL.Simple.QueryResults
>      >�  �  import Database.MySQL.Simple.Result
>      >�  �  import Database.MySQL.Simple.QueryParams
>      >�  �  import Database.MySQL.Simple.Param
>      >�  �  import Control.Monad
>      >�  �  import Data.Text as Text
>      >�  �  --import Data.Int as Int
>      >�  �  --import Data.List
>      >�  �  import Debug.Trace
>      >�  �  import Data.Maybe as Maybe
>      >�  �  -- this function will return th N°BD from Sidonie for a
>      given name
>      >�  �  -- note: names have been standardized between Sidonie and WDS
>      >�  �  getBD3 :: Connection -> String -> Float
>      >�  �  getBD3 conn name = do
>      >�  �  � � � � � � � � � � ��  let
>      qry_head_BD_Sidonie = "select `N° BD` from
>      >�  �  Coordonnées where Nom = ?" :: Query
>      >�  �  � � � � � � � � � � ��  (bd_rows ::
>      [Only Text]) <- query conn
>      >�  �  qry_head_BD_Sidonie (Only (name::String))
>      >�  �  � � � � � � � � � � ��  let noBDtxt =
>      fromOnly (Prelude.head bd_rows) ::
>      >�  �  Text
>      >�  �  � � � � � � � � � � ��  let noBDstr =
>      Text.unpack noBDtxt :: String
>      >�  �  � � � � � � � � � � ��  let noBDfp =
>      read $ noBDstr :: Float
>      >�  �  � � � � � � � � � � ��  return noBDfp
>      >�  �  with this function i have this error:
>      >�  �  Prelude> :load UpdateSidonie
>      >�  �  [1 of 1] Compiling Main� � � � � � � � �
>      � � ��  ( UpdateSidonie.hs,
>      >�  �  interpreted )
>      >�  �  UpdateSidonie.hs:54:13: error:
>      >�  �  � � ��  � Couldn't match expected type �Float�
>      with actual type �IO
>      >�  �  Float�
>      >�  �  � � ��  � In a stmt of a 'do' block:
>      >�  �  � � � � � � ��  (bd_rows :: [Only Text]) <-
>      query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � ��  conn qry_head_BD_Sidonie (Only (name :: String))
>      >�  �  � � � � ��  In the expression:
>      >�  �  � � � � � � ��  do let qry_head_BD_Sidonie =
>      ...
>      >�  �  � � � � � � � � � ��  (bd_rows :: [Only
>      Text]) <- query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � � � � ��  conn qry_head_BD_Sidonie (Only (name ::
>      String))
>      >�  �  � � � � � � � � � ��  let noBDtxt = ...
>      >�  �  � � � � � � � � � ��  let noBDstr = ...
>      >�  �  � � � � � � � � � ��  ....
>      >�  �  � � � � ��  In an equation for �getBD3�:
>      >�  �  � � � � � � � � ��  getBD3 conn name
>      >�  �  � � � � � � � � � � ��  = do let
>      qry_head_BD_Sidonie = ...
>      >�  �  � � � � � � � � � � � � � � �
>      ��  (bd_rows :: [Only Text]) <- query
>      >�  �  � � � � � � � � � � � � � � �
>      � � � � � � � � � � � � � � � � �
>      � � � �
>      >�  �  � � � � � � � � � � ��  conn
>      qry_head_BD_Sidonie (Only (name :: String))
>      >�  �  � � � � � � � � � � � � � � �
>      ��  let noBDtxt = ...
>      >�  �  � � � � � � � � � � � � � � �
>      ��  ....
>      >�  �  � ��  |
>      >�  �  54 |� � � � � � � � � � � ��
>      (bd_rows :: [Only Text]) <- query conn
>      >�  �  qry_head_BD_Sidonie (Only (name::String))
>      >�  �  � ��  |� � � � � � � � � � � �
>      >�  �
>      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>      ^^^
>      >�  �  ^^^^^^^^^
>      >�  �  Failed, no modules loaded.
>      >�  �  i do not understand the error complaining that i return an IO
>      >�  �  float,because i'm sure it's a float in noBDfp
>      >�  �  if i put the same lines of code in the main it works !!! :
>      >�  �  main :: IO ()
>      >�  �  main =
>      >�  �  ��  do
>      >�  �  � � ��  conn <- connect defaultConnectInfo
>      >�  �  � � � � ��  { connectHost = "moita",
>      >�  �  � � � � � � ��  connectUser = "mattei",
>      >�  �  � � � � � � ��  connectPassword = "sidonie2",
>      >�  �  � � � � � � ��  connectDatabase = "sidonie" }
>      >�  �  � let qry_head_BD_Sidonie = "select `N° BD` from
>      Coordonnées where
>      >�  �  Nom = ?" :: Query
>      >�  �  � (bd_rows :: [Only Text]) <- query conn
>      qry_head_BD_Sidonie (Only
>      >�  �  (name::String))
>      >�  �  putStr "bd_rows ="
>      >�  �  putStrLn $ show bd_rows
>      >�  �  � � ��  let noBDtxt = fromOnly (Prelude.head bd_rows)
>      :: Text
>      >�  �  � � ��  let noBDstr = Text.unpack noBDtxt :: String
>      >�  �  � � ��  let noBDfp = read $ noBDstr :: Float
>      >�  �  � � ��  putStr "noBDfp ="
>      >�  �  � � ��  (putStrLn (show noBDfp))
>      >�  �  � close conn
>      >�  �  it works i have output like this:
>      >�  �  *Main> main
>      >�  �  bd_rows =[Only {fromOnly = "-04.3982"}]
>      >�  �  noBDtxt ="-04.3982"
>      >�  �  noBDfp =-4.3982
>      >�  �  noBDfp + 1 = -3.3982
>      >�  �  i'm well getting a float in noBDfp , i even can add 1 to it
>      :-) ( cool
>      >�  �  haskell...)
>      >�  �  but i'm just wanting to that in the function getDB3 but it
>      does not
>      >�  �  compile...
>      >�  �  ??????
>      >�  �  Damien
>      >
>      >�  �  On Sun, Dec 23, 2018 at 4:54 PM Tom Ellis
>      >�  �  <[1][2][hidden email]> wrote:
>      >
>      >�  �  �  I think forgetting about monads and just using do-notation
>      will help
>      >�  �  �  you.
>      >�  �  �  On Sun, Dec 23, 2018 at 04:44:57PM +0100, Damien Mattei
>      wrote:
>      >�  �  �  > i think learning Monads from scratch again will help me
>      >�  �  �  >
>      >�  �  �  > On Sun, Dec 23, 2018 at 4:11 PM Tom Ellis <
>      >�  �  �  > [2][3][hidden email]>
>      wrote:
>      >�  �  �  >
>      >�  �  �  > > Yes, exactly!
>      >�  �  �  > >
>      >�  �  �  > > On Sun, Dec 23, 2018 at 02:08:57PM +0100, Damien
>      Mattei wrote:
>      >�  �  �  > > > lazyness....?
>      >�  �  �  > > >
>      >�  �  �  > > > On Sun, Dec 23, 2018 at 8:40 AM Tom Ellis <
>      >�  �  �  > > > [3][4][hidden email]>
>      wrote:
>      >�  �  �  > > >
>      >�  �  �  > > > > On Sat, Dec 22, 2018 at 09:52:18AM +0100, Damien
>      Mattei
>      >�  �  �  wrote:
>      >�  �  �  > > > > > i have inserted trace statement that output
>      variable
>      >�  �  �  > > > > > ... i have strange behavior of output:
>      >�  �  �  > > > >
>      >�  �  �  > > > > Let's take a simpler example.��  Do you
>      understand why the
>      >�  �  �  trace
>      >�  �  �  > > statments
>      >�  �  �  > > > > from this small program appear in the order that
>      they do?�
>      >�  �  �  (And for
>      >�  �  �  > > what
>      >�  �  �  > > > > it's worth I really think you'll be better off
>      writing
>      >�  �  �  programs using
>      >�  �  �  > > do
>      >�  �  �  > > > > notation).
>      >�  �  �  > > > >
>      >�  �  �  > > > >
>      >�  �  �  > > > > % cat test.hs
>      >�  �  �  > > > > import Debug.Trace
>      >�  �  �  > > > >
>      >�  �  �  > > > > result =
>      >�  �  �  > > > >��  � let a = trace "evaluating a" 2
>      >�  �  �  > > > >��  ��  ��  � b = trace "evaluating b" 10
>      >�  �  �  > > > >��  ��  ��  � c = trace "evaluating c" (a +
>      b)
>      >�  �  �  > > > >��  � in c
>      >�  �  �  > > > > ~% ghci -e result test.hs
>      >�  �  �  > > > > evaluating c
>      >�  �  �  > > > > evaluating b
>      >�  �  �  > > > > evaluating a
>      >�  �  �  > > > > 12
>      >�  �  �  > > _______________________________________________
>      >�  �  �  > > Haskell-Cafe mailing list
>      >�  �  �  > > To (un)subscribe, modify options or view archives go
>      to:
>      >�  �  �  > >
>      [4][5]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  > > Only members subscribed via the mailman list are
>      allowed to
>      >�  �  �  post.
>      >�  �  �  > _______________________________________________
>      >�  �  �  > Haskell-Cafe mailing list
>      >�  �  �  > To (un)subscribe, modify options or view archives go to:
>      >�  �  �  >
>      [5][6]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  > Only members subscribed via the mailman list are allowed
>      to post.
>      >�  �  �  _______________________________________________
>      >�  �  �  Haskell-Cafe mailing list
>      >�  �  �  To (un)subscribe, modify options or view archives go to:
>      >�  �  �
>      [6][7]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  �  Only members subscribed via the mailman list are allowed
>      to post.
>      >
>      > Verweise
>      >
>      >�  �  1. mailto:[8][hidden email]
>      >�  �  2. mailto:[9][hidden email]
>      >�  �  3. mailto:[10][hidden email]
>      >�  �  4.
>      [11]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  5.
>      [12]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>      >�  �  6.
>      [13]http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>
> Verweise
>
>    1. mailto:[hidden email]
>    2. mailto:[hidden email]
>    3. mailto:[hidden email]
>    4. mailto:[hidden email]
>    5. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    6. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    7. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>    8. mailto:[hidden email]
>    9. mailto:[hidden email]
>   10. mailto:[hidden email]
>   11. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>   12. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>   13. http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.