【问题标题】:Haskell function type with IO带 IO 的 Haskell 函数类型
【发布时间】:2011-04-28 09:25:04
【问题描述】:

我对 haskell 中的一些东西感到困惑。首先我会清楚地解释我的问题,

我有从数据库获取结果的函数调用“func1”

类型定义 func1 :: IO[[String]]

func1 = do
 xx <- main --returns the sql output
 return (map (map fromSql) xx :: [[String]])

我需要编写两个函数来给我funcWnt :: IO[[String]] -&gt; [[String]]funcWnt2 :: [String] -&gt; Splice m

我在“funcWnt”中尝试了&lt;-,但没有成功。谁能告诉我如何做到这一点?或任何其他方式做到这一点?'funcWnt2 :: [String] -> 我已经创建,我想知道'funcWnt'函数

thnxxxx!!

【问题讨论】:

  • 再次,没有IO a -&gt; a 类型的函数(其中a 是类型变量),你也不需要。阅读 monad 教程。如果您已经这样做了,请再做一次(也许换一个不同的),因为您似乎错过了一些非常重要的部分。 (另外,main 是程序的开始,理想情况下调用一次 - 为什么要从其他地方显式调用它?将 SQL 获取放入它自己的函数中。)
  • thanxxxx,我将再次阅读 monad 教程。好的,我会更正它,thanxx 再次:-)
  • 检查 IO 问题,或开始 monad 教程。 stackoverflow.com/questions/tagged/…
  • @delnan 好吧,没有 pure 函数 IO a -&gt; a。但是有 unsafePerformIO,它是 Haskell 98 的外部函数接口规范的一部分。
  • @Johnathan:嘘!是的,但是 OP 和大多数其他人甚至没有丝毫使用它的理由,应该只停留在纯洁的境界。

标签: haskell io monads


【解决方案1】:

作为一般性观察:尝试始终考虑您的函数如何处理其输入,假设它们已经得到它们。您的函数似乎既关心获取输入又关心转换它们。让他们只是转换,并使用一些外部函数来获取他们的输入。

让我们看看我们是否可以了解您对此的看法,并按照这些新思路重新制定它:

你有:

readDB :: IO [[SqlValue]]
readDB = ... -- not given here

func1 :: IO [[String]]
func1 = do
  xx <- readDB
  return (map (map fromSql) xx)

你现在想写一些东西来改变它。一种方法是复制您已经使用过的模式:

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

请注意,以func1 的样式编写的这些根本不是函数,而是IO 中的值。如果这些函数不做IO,(而func1 肯定不会),那么用这种方式编写是非惯用的、笨拙的、非模块化的,并将你所有的纯代码放在IO 中。相反,请考虑纯粹编写它们:

func1 :: [[SqlValue]] -> [[String]]
func1 = map (map fromSql)

funcWnt :: [[String]] -> [[String]]
funcWnt = ... -- some transformation

funcWnt2 :: [[String]] -> Splice m
funcWnt2 = ... -- some transformation into a Splice m

现在您可以轻松地组合它们,并在单个 IO 值中使用它们:

dbToSplice :: IO (Splice m)
dbToSplice = do
  xx <- readDB
  return $ (funcWnt2 . funcWnt . func1) xx

或者,也许,更地道(不要害怕&gt;&gt;=,早点学习):

dbToSplice :: IO (Splice m)
dbToSplice = readDB >>= return . funcWnt2 . funcWnt . func1

现在,如果只是为了争论,funcWnt2 需要在IO 中做某事。然后定义看起来像:

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

最后,请注意我在每个顶级函数上都放置了类型签名。你也应该养成这样做的习惯。它不仅有助于澄清您的意图(对您自己、其他开发人员,甚至是一周后的您自己),而且还消除了许多尴尬的类型注释,比如您必须在 func1 中添加。

【讨论】:

    猜你喜欢
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多