如何展平 IO [[String]]? [英] How to flatten IO [[String]]?
问题描述
我是 Haskell 的新手,在理解它的一些概念时遇到了一些困难.
I am new to Haskell and have some difficulties wrapping my head around some of it's concepts.
在玩 IO 时,我想扁平化一个 IO [[String]].
While playing around with IO I wanted to flatten an IO [[String]].
我尝试过的示例:
module DatabaseTestSO where
import Database.HDBC
import Database.HDBC.MySQL
import Data.Foldable
convSqlValue :: [SqlValue] -> [String]
convSqlValue xs = [ getString x | x <- xs ]
where getString value = case fromSql value of
Just x -> x
Nothing -> "Null"
listValues :: [[SqlValue]] -> [[String]]
listValues [] = []
listValues xs = [ convSqlValue x | x <- xs ]
flatten :: [[a]] -> [a]
flatten = Data.Foldable.foldl (++) []
domains :: IO [[String]]
domains =
do conn <- connectMySQL defaultMySQLConnectInfo {
mysqlHost = "hostname",
mysqlDatabase = "dbname",
mysqlUser = "username",
mysqlPassword = "pass" }
queryDomains <- quickQuery conn "SELECT name FROM domains" []
return (listValues queryDomains)
按预期与 GHCi 中的 [[String]]
一起使用:
That works with [[String]]
in GHCi as expected:
*DatabaseTestSO> flatten [["blah","blab","wah"],["bloh","blob","woh"],["blih","blib","wuh"]]
["blah","blab","wah","bloh","blob","woh","blih","blib","wuh"]
但不使用 IO [[String]]
我得到的地方
but does not with IO [[String]]
where I get
*DatabaseTestSO> flatten domains
<interactive>:1:9:
Couldn't match expected type `[[a0]]'
with actual type `IO [[String]]'
In the first argument of `flatten', namely `domains'
In the expression: flatten domains
In an equation for `it': it = flatten domains
我想我不能使用应该是纯 IO 类型的函数?我可以将 IO [[String]]
转换为 [[String]]
吗?我该如何正确解决这个问题?
I guess I can not use a function that is supposed to be pure with IO types?
Can I convert IO [[String]]
to [[String]]
?
How do I solve this problem correctly?
推荐答案
您必须了解 IO something
的含义.这不是一个 something
,它是一个 action 将返回一个 something
(在这种情况下,something
是 [[字符串]]
).所以,你不能对动作返回的东西做任何事情,直到你执行了返回那个东西的动作.
You have to realize what IO something
means. It's not a something
, it's an action that will return a something
(In this case, something
is [[String]]
). So, you cannot do anything with the thing that the action returns, until you perform the action, which returns that thing.
您有两种选择来解决您的问题.
You have two options to solve your problem.
执行操作,并使用结果.这是这样做的:
Perform the action, and use the result. This is done like this:
do
ds <- domains -- Perform action, and save result in ds
return $ flatten ds -- Flatten the result ds
创建一个新的动作,它接受某个动作的结果,并对其应用一个函数.然后新操作返回转换后的值.这是通过 Control.Monad
模块中的 liftM
函数完成的.
Create a new action that takes the result of some action, and applies a function to it. The new action then returns the transformed value. This is done with the liftM
function in the Control.Monad
module.
import Control.Monad
-- ...
do
-- Creates a new action that flattens the result of domains
let getFlattenedDomains = liftM flatten domains
-- Perform the new action to get ds, which contains the flattened result
ds <- getFlattenedDomains
return ds
附注.您可能希望将 domains
变量重命名为 getDomains
以阐明它的作用.这不是一个纯粹的价值;这是一个返回纯值的单子操作.
PS. You might want to rename your domains
variable to getDomains
to clarify what it does. It's not a pure value; it's a monadic action that returns a pure value.
这篇关于如何展平 IO [[String]]?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!