[Haskell-cafe] trace output statements

Ian Denhardt ian at zenhack.net
Tue Dec 25 21:17:27 UTC 2018


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]tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> 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]tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> 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]tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> 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:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
>    2. mailto:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
>    3. mailto:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
>    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


More information about the Haskell-Cafe mailing list