[Haskell-cafe] trace output statements

Damien Mattei damien.mattei at gmail.com
Wed Dec 26 22:24:53 UTC 2018


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 <ian at zenhack.net> 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]ian at zenhack.net>
> >    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]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][3]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][4]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][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]tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >      >�  �  2. mailto:[9]tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >      >�  �  3. mailto:[10]tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >      >�  �  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:ian at zenhack.net
> >    2. mailto:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >    3. mailto:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >    4. mailto:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >    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:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >    9. mailto:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >   10. mailto:tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk
> >   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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20181226/9a916510/attachment.html>


More information about the Haskell-Cafe mailing list