我是通过Haskell语言编程的初学者。我有兴趣在Haskell中编写函数,它有这样的副作用(出于教育目的,它可能有另一个副作用):
-- function foo behaves like random numbers generator
foo :: Int
{- foo = some magic -}
-- It can print True or False
print $ show (foo /= foo)
据我所知,我必须用这样的行为实现Monad的某种类型实例(如:IO Why are side-effects modeled as monads in Haskell?)。但我真的不明白如何为此目的编写简单的函数示例。
答案 0 :(得分:1)
如果foo
真的像某些RNG一样,它必须具有一些monadic类型,或者作为RNG状态的附加输入。
这是一个例子,使用系统RNG(住在IO monad):
import System.Random
foo :: IO Int
foo = randomRIO (1,5) -- random number between 1 and 5
main :: IO ()
main = do
x <- foo
y <- foo
print $ x /= y
在main
中,我们只需拨打foo
两次,将其结果绑定到x,y
,其类型为Int
。然后,我们可以照常比较它们。
请注意,我们无法使用foo /= foo
foo :: IO Int
,这是一个返回Int的操作,我们无法比较操作,只能比较基本数据,如整数。这就是为什么我们首先执行操作,然后比较它们的结果。
可以使用一些更高级的组合器在一行中编写main
main = print =<< ((/=) <$> foo <*> foo)
-- or
main = print =<< liftA2 (/=) foo foo
但我不会在开始时关注这些。
一个侧面有效计算的更一般的例子:
foo :: IORef String -> IO Int
foo s = do
x <- readIORef s -- reading a "variable"
print x -- output
w <- getLine -- input
writeIORef s ("qwerty" ++ x) -- writing a variable
length <$> readIORef s
main :: IO ()
main = do
s <- newIORef "dummy"
print =<< foo s