Haskell function type with IO
I'm confusing w开发者_如何转开发ith some stuff in haskell.First I'll explain my problem clearly,
I have function call "func1" that take result from the DB
type definition
func1 :: IO[[String]]
func1 = do
xx <- main --returns the sql output
return (map (map fromSql) xx :: [[String]])
I need to write two functions that gives me funcWnt :: IO[[String]] -> [[String]]
and funcWnt2 :: [String] -> Splice m
I tried <-
within "funcWnt" but that was not succeed.Could any one tell me how to do this?or any other way to do this?'funcWnt2 :: [String] -> I have created,I want to know 'funcWnt' function
thnxxxx!!
As a general observation: Try to always think about what your functions do with their inputs, assuming they've already got them. Your functions seem to be concerned with both getting their inputs and transforming them. Let them just transform, and use some outer function to get them their inputs.
Let's see if we can take how you're thinking of this, and re-formulate it along these new lines:
You have:
readDB :: IO [[SqlValue]]
readDB = ... -- not given here
func1 :: IO [[String]]
func1 = do
xx <- readDB
return (map (map fromSql) xx)
You now want to write something that transforms this. One way is to just replicate the pattern you've already used:
funcWnt :: IO [[String]]
yy <- func1
return ... -- some transformation of yy
funcWnt2 :: IO (Splice m)
zz <- funcWnt
return ... -- some transformation of zz into a Splice m
Notice that written in the style of func1
these are not functions at all, but values in IO
. If these functions don't do IO
, (and func1
certainly doesn't), then writing this way is non-idiomatic, awkward, non-modular, and puts all your pure code inside IO
. Instead, consider writing them purely:
func1 :: [[SqlValue]] -> [[String]]
func1 = map (map fromSql)
funcWnt :: [[String]] -> [[String]]
funcWnt = ... -- some transformation
funcWnt2 :: [[String]] -> Splice m
funcWnt2 = ... -- some transformation into a Splice m
Now you can easily combine them, and use them in a single IO
value:
dbToSplice :: IO (Splice m)
dbToSplice = do
xx <- readDB
return $ (funcWnt2 . funcWnt . func1) xx
Or perhaps, more idiomatically (don't be afraid of >>=
, learn it early):
dbToSplice :: IO (Splice m)
dbToSplice = readDB >>= return . funcWnt2 . funcWnt . func1
Now, if, just for sake of argument, funcWnt2
needed to do something in IO
. Then the definitions would look like:
funcWnt2 :: [[String]] -> IO (Splice m)
funcWnt2 zz = do
... -- compute something with zz
return ... -- returning some Splice m
dbToSplice :: IO (Splice m)
dbToSplice = readDB >>= funcWnt2 . funcWnt . func1
Lastly, notice that I put type signatures on every top level function. You should get in the habit of doing this too. Not only does it help clarify your intent (to yourself, other developers, or even yourself a week from now), but it eliminates many awkward type annotations like you had to put inside func1
.
精彩评论