I'm having a little Haskell Situation over here. I'm trying to write two functions with monads. First one is supposed to iterate through a function as long as the condition is true for the input / output of the function. Second one is supposed to use the first one to take a number as input and write it as output until you enter a space.
我在这里有一点Haskell情况。我正在尝试用monad编写两个函数。只要条件对于函数的输入/输出为真,第一个应该遍历函数。第二个应该使用第一个作为输入的数字并将其作为输出写入,直到您输入空格。
I'm stuck with this, any help?
我坚持这个,有什么帮助吗?
module Test where
while :: (a -> Bool) -> (a -> IO a) -> a -> IO a
while praed funktion x = do
f <- praed (funktion x)
if f == True then do
y <- funktion x
while praed funktion y
else return x
power2 :: IO ()
power2 = do putStr (Please enter a number.")
i <- getChar
while praed funktion
where praed x = if x /= ' ' then False else True
funktion = i
2 个解决方案
#1
11
import Control.Monad
while :: (a -> Bool) -> (a -> IO a) -> a -> IO a
while praed funktion x
| praed x = do
y <- funktion x
while praed funktion y
| otherwise = return x
power2 :: IO ()
power2 = do
putStr "Please enter a number."
i <- getChar
let praed x = x /= ' '
let f x = do
putChar x
getChar
while praed f '?'
return ()
Some notes:
一些说明:
- Using
if x then True else False
is redundant, it's equivalent to justx
. - 使用if x然后是True否则False是多余的,它只相当于x。
- Similarly
if x == True ...
is redundant and equivalent toif x ...
. - 同样,如果x == True ...是多余的,相当于if x ....
-
You need to distinguish between
IO
actions and their results. For example, if yo do您需要区分IO操作及其结果。例如,如果哟
do i <- getChar ...
then in ...
i
represents the result of the action, a character, soi :: Char
. ButgetChar :: IO Char
is the action itself. You can view it as a recipe that returnsChar
when performed. You can pass the recipe around to functions etc., and it is only performed when executed somewhere.然后在......我代表动作的结果,一个角色,所以i :: Char。但是getChar :: IO Char就是动作本身。您可以将其视为在执行时返回Char的配方。您可以将配方传递给函数等,只有在某处执行时才会执行。
-
Your
while
calledfunktion
twice, which probably isn't what you intend - it would read a character twice, check the first one and return the second one. Remember, yourfunktion
is an action, so each time you "invoke" the action (for example by using<- funktion ...
in thedo
notation), the action is run again. So it should rather be something like你被称为funktion两次,这可能不是你想要的 - 它会读取一个字符两次,检查第一个并返回第二个。请记住,您的功能是一个动作,因此每次“调用”动作时(例如,通过在符号中使用< - funktion ...),动作将再次运行。所以它应该是类似的东西
do y <- funktion x f <- praed y -- ...
(My code is somewhat different, it checks the argument that is passed to it.)
(我的代码有些不同,它会检查传递给它的参数。)
#2
3
For a pure version:
对于纯版本:
{-# LANGUAGE BangPatterns #-}
while :: (a -> Bool) -> (a -> a) -> a -> a
while p f = go where go !x = if p x then go (f x) else x
test1 :: Int
test1 = while (< 1000) (* 2) 2
-- test1 => 1024
for monadic:
对于monadic:
import Control.Monad
whileM :: (Monad m, MonadPlus f) => (a -> m Bool) -> m a -> m (f a)
whileM p f = go where
go = do
x <- f
r <- p x
if r then (return x `mplus`) `liftM` go else return mzero
test2 :: IO [String]
test2 = whileM (return . (/= "quit")) getLine
-- *Main> test2
-- quit
-- []
-- *Main> test2
-- 1
-- 2
-- 3
-- quit
-- ["1","2","3"]
power2 :: IO (Maybe Char)
power2 = whileM (return . (/= 'q')) getChar
-- *Main> power2
-- q
-- Nothing
-- *Main> power2
-- 1
-- 2
-- 3
-- q
-- Just '\n'
see also:
也可以看看:
http://hackage.haskell.org/package/monad-loops, http://hackage.haskell.org/package/loop-while, http://hackage.haskell.org/package/control-monad-loop.
http://hackage.haskell.org/package/monad-loops,http://hackage.haskell.org/package/loop-while,http://hackage.haskell.org/package/control-monad-loop。
http://www.haskellforall.com/2012/01/haskell-for-c-programmers-for-loops.html
http://www.haskellforall.com/2012/01/haskell-for-c-programmers-for-loops.html
#1
11
import Control.Monad
while :: (a -> Bool) -> (a -> IO a) -> a -> IO a
while praed funktion x
| praed x = do
y <- funktion x
while praed funktion y
| otherwise = return x
power2 :: IO ()
power2 = do
putStr "Please enter a number."
i <- getChar
let praed x = x /= ' '
let f x = do
putChar x
getChar
while praed f '?'
return ()
Some notes:
一些说明:
- Using
if x then True else False
is redundant, it's equivalent to justx
. - 使用if x然后是True否则False是多余的,它只相当于x。
- Similarly
if x == True ...
is redundant and equivalent toif x ...
. - 同样,如果x == True ...是多余的,相当于if x ....
-
You need to distinguish between
IO
actions and their results. For example, if yo do您需要区分IO操作及其结果。例如,如果哟
do i <- getChar ...
then in ...
i
represents the result of the action, a character, soi :: Char
. ButgetChar :: IO Char
is the action itself. You can view it as a recipe that returnsChar
when performed. You can pass the recipe around to functions etc., and it is only performed when executed somewhere.然后在......我代表动作的结果,一个角色,所以i :: Char。但是getChar :: IO Char就是动作本身。您可以将其视为在执行时返回Char的配方。您可以将配方传递给函数等,只有在某处执行时才会执行。
-
Your
while
calledfunktion
twice, which probably isn't what you intend - it would read a character twice, check the first one and return the second one. Remember, yourfunktion
is an action, so each time you "invoke" the action (for example by using<- funktion ...
in thedo
notation), the action is run again. So it should rather be something like你被称为funktion两次,这可能不是你想要的 - 它会读取一个字符两次,检查第一个并返回第二个。请记住,您的功能是一个动作,因此每次“调用”动作时(例如,通过在符号中使用< - funktion ...),动作将再次运行。所以它应该是类似的东西
do y <- funktion x f <- praed y -- ...
(My code is somewhat different, it checks the argument that is passed to it.)
(我的代码有些不同,它会检查传递给它的参数。)
#2
3
For a pure version:
对于纯版本:
{-# LANGUAGE BangPatterns #-}
while :: (a -> Bool) -> (a -> a) -> a -> a
while p f = go where go !x = if p x then go (f x) else x
test1 :: Int
test1 = while (< 1000) (* 2) 2
-- test1 => 1024
for monadic:
对于monadic:
import Control.Monad
whileM :: (Monad m, MonadPlus f) => (a -> m Bool) -> m a -> m (f a)
whileM p f = go where
go = do
x <- f
r <- p x
if r then (return x `mplus`) `liftM` go else return mzero
test2 :: IO [String]
test2 = whileM (return . (/= "quit")) getLine
-- *Main> test2
-- quit
-- []
-- *Main> test2
-- 1
-- 2
-- 3
-- quit
-- ["1","2","3"]
power2 :: IO (Maybe Char)
power2 = whileM (return . (/= 'q')) getChar
-- *Main> power2
-- q
-- Nothing
-- *Main> power2
-- 1
-- 2
-- 3
-- q
-- Just '\n'
see also:
也可以看看:
http://hackage.haskell.org/package/monad-loops, http://hackage.haskell.org/package/loop-while, http://hackage.haskell.org/package/control-monad-loop.
http://hackage.haskell.org/package/monad-loops,http://hackage.haskell.org/package/loop-while,http://hackage.haskell.org/package/control-monad-loop。
http://www.haskellforall.com/2012/01/haskell-for-c-programmers-for-loops.html
http://www.haskellforall.com/2012/01/haskell-for-c-programmers-for-loops.html