简体   繁体   English

Haskell function型带IO

[英]Haskell function type with IO

I'm confusing with some stuff in haskell.First I'll explain my problem clearly,我对 haskell 中的一些东西感到困惑。首先我会清楚地解释我的问题,

I have function call "func1" that take result from the DB我有从数据库获取结果的 function 调用“func1”

type definition func1:: IO[[String]]类型定义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我需要编写两个函数来给我funcWnt:: IO[[String]] -> [[String]]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我在“funcWnt”中尝试了<- ,但没有成功。有人能告诉我怎么做吗?或有其他方法吗?'funcWnt2:: [String] -> 我已经创建,我想知道' 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.让他们只是转换,并使用一些外部 function 来获取他们的输入。

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 .请注意,以func1的样式编写的这些根本不是函数,而是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 .如果这些函数不做IO ,(而func1当然不做),那么用这种方式编写是非惯用的、笨拙的、非模块化的,并将所有纯代码放入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:现在您可以轻松地组合它们,并在单个IO值中使用它们:

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 .现在,如果只是为了争论, funcWnt2需要在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.最后,请注意我在每个顶级 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 .它不仅有助于澄清你的意图(对你自己、其他开发人员,甚至是一周后的你自己),而且它消除了许多尴尬的类型注释,比如你必须放在func1中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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