如何展平 IO [[String]]? [英] How to flatten IO [[String]]?

查看:16
本文介绍了如何展平 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.

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

  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

  • 创建一个新的动作,它接受某个动作的结果,并对其应用一个函数.然后新操作返回转换后的值.这是通过 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屋!

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