实践中
不,不能这样做,至少不能以有意义的方式。
考虑一下这个 Haskell 代码
action :: Int -> IO String
action n = print n >> getLine
这首先需要n,打印它(在这里执行IO),然后从用户那里读取一行。
假设我们有一个假设的transform :: (a -> IO b) -> IO (a -> b)。然后作为一个心理实验,考虑:
action' :: IO (Int -> String)
action' = transform action
上面要提前做好所有的IO,才知道n,然后返回一个纯函数。这不能等同于上面的代码。
为了强调这一点,请考虑下面这段无意义的代码:
test :: IO ()
test = do f <- action'
putStr "enter n"
n <- readLn
putStrLn (f n)
神奇的是,action' 应该提前知道用户接下来要输入什么!会话看起来像
42 (printed by action')
hello (typed by the user when getLine runs)
enter n
42 (typed by the user when readLn runs)
hello (printed by test)
这需要时间机器,所以无法完成。
理论上
不,不能这样做。参数类似于the one I gave to a similar question。
假设存在矛盾transform :: forall m a b. Monad m => (a -> m b) -> m (a -> b)。
将 m 专门用于延续单子 ((_ -> r) -> r)(我省略了 newtype 包装器)。
transform :: forall a b r. (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r
专精r=a:
transform :: forall a b. (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a
申请:
transform const :: forall a b. ((a -> b) -> a) -> a
根据 Curry-Howard 同构,以下是直觉重言式
((A -> B) -> A) -> A
但这是皮尔斯定律,在直觉逻辑中无法证明。矛盾。