将 (a -> IO b) 转换为 IO (a -> b)
Transformation of (a -> IO b) to IO (a -> b)
我在 IO 上下文中有多种数据类型,例如:
a :: IO String
b :: IO FilePath
c :: String -> IO String
我想将它们全部放在一个数据对象中,例如:
data Configdata = Configdata String FilePath (String -> String)
所以我不必从 IO 上下文中获取每个值,而只是从 IO Configdata
.
中获取
我没有解决方案的关键点是如何将 String -> IO String
转换为 IO (String -> String)
。
Hoogle 没有给我任何能够做到这一点的功能。
我不确定这是否可能甚至不可能,因为函数的输入可能是无限的。
有人有解决方案或解释为什么这是不可能的吗?
我知道使用列表而不是函数是一种选择,但我更愿意尽可能使用函数。
这确实不可能。考虑函数:
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 liquid pain"
现在,如果可以将其转换为 IO (String -> String)
,则必须在返回纯 String -> String
函数之前执行 all possible IO
actions for any input。 IOW,即使你只打算使用该功能来观看小猫,它也会带来核浩劫。
不过,很可能针对您的特定应用程序执行此操作。特别是,如果您知道只会针对一组预先确定的字符串调用该函数,您可以从 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)
当然,这在性能方面可能不可行。
我在 IO 上下文中有多种数据类型,例如:
a :: IO String
b :: IO FilePath
c :: String -> IO String
我想将它们全部放在一个数据对象中,例如:
data Configdata = Configdata String FilePath (String -> String)
所以我不必从 IO 上下文中获取每个值,而只是从 IO Configdata
.
我没有解决方案的关键点是如何将 String -> IO String
转换为 IO (String -> String)
。
Hoogle 没有给我任何能够做到这一点的功能。
我不确定这是否可能甚至不可能,因为函数的输入可能是无限的。
有人有解决方案或解释为什么这是不可能的吗? 我知道使用列表而不是函数是一种选择,但我更愿意尽可能使用函数。
这确实不可能。考虑函数:
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 liquid pain"
现在,如果可以将其转换为 IO (String -> String)
,则必须在返回纯 String -> String
函数之前执行 all possible IO
actions for any input。 IOW,即使你只打算使用该功能来观看小猫,它也会带来核浩劫。
不过,很可能针对您的特定应用程序执行此操作。特别是,如果您知道只会针对一组预先确定的字符串调用该函数,您可以从 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)
当然,这在性能方面可能不可行。