如何拼合IO [[String]]? [英] How to flatten IO [[String]]?

查看:78
本文介绍了如何拼合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>


  1. 执行操作并使用结果。这是这样做的:

      do 
    ds < - domains - 执行操作并将结果保存到ds
    return $ flatten ds - 展示结果ds


  2. 创建一个新动作它采取某种行动的结果,并对其应用一个函数。新的动作然后返回转换后的值。这是通过 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.

  1. 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
    

  2. 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
    

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆