4

我在 IO 上下文中有几种数据类型,例如:

a :: IO String
b :: IO FilePath
c :: String -> IO String

我想将它们全部放在一个数据对象中,例如:

data Configdata = Configdata String FilePath (String -> String)

所以我不必从 IO 上下文中获取每个值,而只需从IO Configdata.

我没有解决方案的关键点是如何转换String -> IO StringIO (String -> String). Hoogle 没有给我任何能够做到这一点的功能。

我不确定这是否可能,因为函数的输入可能是无限的。

有人有解决方案或解释为什么不可能吗?我知道使用列表而不是函数是一种选择,但如果可能的话,我更喜欢使用函数。

4

1 回答 1

10

确实这是不可能的。考虑函数:

import Acme.Missiles

boo :: String -> IO String
boo "cute" = return "Who's a nice kitty?"
boo "evil" = launchMissiles >> return "HTML tags lea͠ki̧n͘g fr̶ǫm ̡yo​͟ur eye͢s̸ ̛l̕ik͏e liq​uid pain"

现在,如果可以将 this 转换为IO (String -> String),则必须在返回纯函数之前对任何输入执行所有可能的操作。IOString -> StringIOW,即使您只打算将该功能用于观看小猫的目的,也将导致核浩劫。

尽管如此,对于您的特定应用程序来说,这样做是可能的。特别是,如果您知道该函数只会为一组预定的字符串调用,您可以从映射中预查询它们IO并将结果存储在映射中,然后可以对其进行纯粹的索引。

import qualified Data.Map as Map

puh :: IO (String -> String)
puh = fmap ((Map.!) . Map.fromList) . forM ["cute"] $ \q -> do
       res <- boo q
       return (q, res)

当然,这在性能方面可能不可行。

于 2016-08-18T14:16:28.237 回答