
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) :
https://stackoverflow.com/questions/27947925/haskell-prelude-read-no-parse-s...
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
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
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@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@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@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@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@jaguarpaw.co.uk >� � 2. mailto:[9]tom-lists-haskell-cafe-2017@jaguarpaw.co.uk >� � 3. mailto:[10]tom-lists-haskell-cafe-2017@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@zenhack.net 2. mailto:tom-lists-haskell-cafe-2017@jaguarpaw.co.uk 3. mailto:tom-lists-haskell-cafe-2017@jaguarpaw.co.uk 4. mailto:tom-lists-haskell-cafe-2017@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@jaguarpaw.co.uk 9. mailto:tom-lists-haskell-cafe-2017@jaguarpaw.co.uk 10. mailto:tom-lists-haskell-cafe-2017@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