如何拼合IO [[String]]? [英] How to flatten IO [[String]]?
问题描述
在IO中玩耍的时候,我想把一个IO扁平化[[String
我尝试过的一个例子:
module DatabaseTestSO where
import Database.HDBC
import Database.HDBC.MySQL
import Data.Foldable
convSqlValue :: [SqlValue] - > [String]
convSqlValue xs = [getString x | x< - xs]
其中,getString的值=来自Sql值的
的情况只要x - > x
Nothing - > 空
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,$ b $ mysqlPassword =pass}
queryDomains< - quickQuery connSELECT name FROM domains[]
return(listValues queryDomains)
与GHci中的 [[String]]
一起使用:
* DatabaseTestSO> flatten [[blah,blab,wah],[bloh,blob,woh],[blih,blib,wuh]]
[ blah,blab,wah,bloh,blob,woh,blih,blib,wuh]
但不包含 IO [[String]]
我得到的地方
* DatabaseTestSO>拼合域
< interactive>:1:9:
无法与实际类型为`IO [[String]]的预期类型`[[a0]]'
匹配'
在'flatten'的第一个参数中,即`domains'
在表达式中:flatten domains
在'it'的等式中:it = flatten domains
我猜我不能使用一个IO类型纯粹的函数吗?
我可以将 IO [[String]]
转换为 [[String]]
?
如何正确解决此问题?
您必须了解 IO
的意思。它不是某物
,它是一个动作,它会返回一个一些东西
, something
是 [[String]]
)。所以,你不能对动作返回的东西做任何事情,直到你执行了返回该事件的动作。
你有两个选择来解决你的问题。 / p>
-
执行操作并使用结果。这是这样做的:
do
ds < - domains - 执行操作并将结果保存到ds
return $ flatten ds - 展示结果ds
-
创建一个新动作它采取某种行动的结果,并对其应用一个函数。新的动作然后返回转换后的值。这是通过
Control.Monad
模块中的liftM
函数完成的。import Control.Monad
- ...
do
- 创建一个新的动作,使结果变平域名
让getFlattenedDomains = liftM拼合域
- 执行新动作以获取包含展平结果的ds
ds < - getFlattenedDomains
return ds
您可能想要将域
变量重命名为 getDomains
,以澄清它的功能。这不是一个纯粹的价值;这是一个monadic动作,返回一个纯粹的值。
I am new to Haskell and have some difficulties wrapping my head around some of it's concepts.
While playing around with IO I wanted to flatten an IO [[String]].
An example of what I have tried:
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)
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"]
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
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?
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
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 theControl.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
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屋!