函数o1 .. o3尽管做了最大的努力但从未打过电话

时间:2016-09-24 18:51:35

标签: haskell

module Main(main) where 

import Text.Printf

data RxEvent a =
    Value a
    | Error String
    | Done
    deriving (Show,Eq)

notify :: (Monad m, Foldable t, Num a1) => t (RxEvent a -> t1) -> RxEvent a -> m a1
notify subs ev =
    return $ Prelude.foldl (\ c s -> seq (s ev) (c+1) ) 0 subs

o name ev = do
    putStrLn name
    print ev
    return 0

o1 = o "o1:"
o2 = o "o2:"
o3 = o "o3:"

main = do
    nNotified <- notify [o1,o2,o3] (Value 42) :: IO Int
    printf "%d subscribers notified\n" nNotified
    return ()

看来,seq在上面的代码段中失败了。 foldl函数访问列表中的所有3个成员,但是函数o1 o2 o3中没有输出。这次我做错了什么? :)

使用:main在ghci中运行只生成“3个订阅者通知”,但没有来自它应该通知的函数的输出。

2 个答案:

答案 0 :(得分:5)

seq确保评估IO个操作,但不执行。例如

print (seq (print 45) 12)

打印“12”,而不是“45 12”。对print 45部分进行评估,以生成IO ()值,但该值永远不会执行。

要运行IO操作,您必须直接或间接使用>>=

答案 1 :(得分:1)

我已经意识到目标函数的调用应该在monadic上下文中。所以,记住隐秘有意义的_函数以及我偶然看到的M结尾的函数,我尝试了像:t foldlM:t foldlM_这样的ghci,但当然他们不在范围内,因为它们在Control.Monad包内。我没有提到的包裹......

对我的问题的评论赞不绝口,我的代码片段的工作版本如下所示:

module Main(main) where 

import Text.Printf
import Control.Monad

data RxEvent a =
    Value a
    | Error String
    | Done
    deriving (Show,Eq)

notify :: (Foldable t, Num b, Monad m) => t (RxEvent t1 -> m a) -> RxEvent t1 -> m b
notify subs ev = foldM (\ c s -> s ev >> return (c+1)) 0 subs

o name ev = do
    putStrLn name
    print ev
    return 0

o1 = o "o1:"
o2 = o "o2:"
o3 = o "o3:"

main = do
    nNotified <- notify [o1,o2,o3] (Value 42) :: IO Int
    printf "%d subscribers notified\n" nNotified
    return ()

获得的经验教训:对于那些试图以经验方式单独学习Haskell的人而不花费数小时来了解随机数量的软件包,可以预期会遇到这些非常简单的问题。

我仍然不太明白的是,为什么Control.Monad的内容是在一个额外的包中而不是Prelude的一部分,因为没有这些功能,就不可能有任何简单的事情......

这里,最后希望输出:

o1:
Value 42
o2:
Value 42
o3:
Value 42
3 subscribers notified