简体   繁体   中英

Haskell function type with IO

I'm confusing with 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM