我有一个函数(来自库)接受另一个函数作为参数:
func :: ( a -> b ) -> a -> m()
但是现在,我想将一个生成 Monadic 结果的函数应用于
func
:
funcArg :: a -> m b
所以
func
实际上需要是func :: ( a -> mb ) -> a -> m()
我有一种感觉,
func
可以提升为m
,而得到的m ( m() )
可以变成所需的m()
。但我现在真的只是猜测。
我该怎么办?任何提示都将受到高度赞赏。
编辑: 我给出的类型签名不准确。应该是
func :: ( a -> b ) -> c -> m()
。具体签名是 Gloss animate :: Display -> Color -> ( Float -> Picture ) -> IO()
中的 animate 函数。虽然我的函数有签名 ( Float -> IO Picture )
。在这种情况下使用的正确函数是 animateIO
。
我是初学者,所以请不要相信我的话。经验丰富的 Haskellers 很可能会建议不要这样做。但既然你要求提示,这就是我的尝试。
首先,我检查了此类型检查:
func :: a -> b -> (Float -> c) -> IO ()
func = undefined
funcArg :: Float -> IO a
funArg = undefined
-- This seems to be essentially what is desired
transform :: (Float -> IO a) -> (Float -> a)
transform = undefined
-- So that a tranformed 'funcArg' can be plugged into 'func'
composed :: a -> b -> IO ()
composed x y = func x y (transform funcArg)
这个进行类型检查,所以问题变成了如何从单子动作中提取值。从这个链接的讨论来看,似乎没有通用的方法可以做到这一点。不同的 monad 将有其特定的方法(例如
fromMaybe
代表 Maybe
monad)。此外,在该线程中,有人建议从 unsafePerformIO
中选择 System.IO.Unsafe
。
如果您确定该操作的安全性,您可以这样做:
import System.IO.Unsafe (unsafePerformIO)
然后
transform f = \x -> unsafePerformIO (f x)
文档说:“为了安全起见,IO计算应该没有副作用并且独立于其环境。”您必须亲自检查一下。
我希望这有帮助。如果没有别的事,我希望类型检查练习能够帮助您找到您想要的东西。