我正在阅读文章使用 Conor McBride和Ross Paterson的效果进行Applcative编程,我无法弄清楚为什么他们的第一段代码类型检查.(我有强大的OCaml背景和弱的haskell背景).
有一个函数ap来自Control.Monad以下类型:
ap :: Monad m => m (a -> b) -> m a -> m b
Run Code Online (Sandbox Code Playgroud)
这个函数很容易写成这样:
ap mf mx = do { f <- mf ; x <- mx ; return (f x) }
Run Code Online (Sandbox Code Playgroud)
然后他们写下以下内容:
sequence :: [IO a] ? IO [a]
sequence [] = return []
sequence (c : cs) = return (:) `ap` c `ap` sequence cs
Run Code Online (Sandbox Code Playgroud)
我的问题是我无法弄清楚如何计算(:) `ap` c `ap` sequence cs手工类型,因为它的类型(:)是无处不m (a -> b)在的a -> ([a] -> [a]).
该类型的ap (Just (:))是Maybe a -> (Maybe ([a] -> [a])),正如预期,但该typechecker告诉我,类型ap (:)是(a -> [a]) -> a -> [a].这怎么可能?
如果你在写作
return (:) `ap` c `ap` sequence cs
Run Code Online (Sandbox Code Playgroud)
然后,通过明确的括号,它是
((return (:)) `ap` c) `ap` (sequence cs)
Run Code Online (Sandbox Code Playgroud)
所以,
(:) :: a -> [a] -> [a]
return (:) :: IO (a -> [a] -> [a])
c :: IO a
(return (:)) `ap` c :: IO ([a] -> [a])
sequence cs :: IO [a]
((return (:)) `ap` c) `ap` cs :: IO [a]
Run Code Online (Sandbox Code Playgroud)
对于你的第二个问题,ap (:)是使用Monad实例(->) a,在哪里
-- Monad instance for ((->) a)
return x = \_ -> x
x >>= f = \y -> f (x y) y
Run Code Online (Sandbox Code Playgroud)
所以你有了:
ap :: (a -> (b -> c)) -> (a -> b) -> (a -> c)
ap f g = \x -> f x (g x)
Run Code Online (Sandbox Code Playgroud)
如果您只是查看了do-block定义ap并扩展了定义.
有可能第二个问题现在可能不会太重要或不重要; 现在关注第一个答案:)
| 归档时间: |
|
| 查看次数: |
106 次 |
| 最近记录: |