我正在Haskell Wiki:https://en.wikibooks.org/wiki/Haskell/Higher-order_functions
中尝试此练习以下练习结合了您所学的高级知识 订单功能,递归和I / O。我们将重现什么是 在命令式语言中称为 for 循环。实现功能
for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO () for i p f job = -- ???
到目前为止,我有:
-- for : init value, end condition function, increment function, IO function,
-- returns IO action
generate :: a -> (a->Bool) -> (a->a) -> [a]
generate s cnd incr = if (cnd s) then [] else [s] ++ generate (incr s) cnd incr
printToList = do
u <- print 1
v <- print 2
return [u,v]
ioToASingle :: [IO a] -> IO [a]
ioToASingle (x:xs) = do
x' <- x
return [x']
sequenceIO :: [IO a] -> IO [a]
sequenceIO [] = return []
sequenceIO (x:xs) = do
x' <- x
xs' <- sequenceIO xs
return ([x'] ++ xs')
for::a->(a->Bool)->(a->a)->(a->IO())->IO()
for s cnd incr ioFn = sequence_ (map (ioFn) (generate s cnd incr))
for'::a->(a->Bool)->(a->a)->(a->IO a)->IO [a]
for' s cnd incr ioFn = sequenceIO (map (ioFn) (generate s cnd incr))
for
可以正常运行:
for 1 (\i->i==10) (\i->i+1) (print)
1
2
3
4
5
6
7
8
9
for'
出现错误:
*Main> for' 1 (\i->i==10) (\i->i+1) (print)
<interactive>:323:6: error:
• No instance for (Num ()) arising from the literal ‘1’
• In the first argument of ‘for'’, namely ‘1’
In the expression: for' 1 (\ i -> i == 10) (\ i -> i + 1) (print)
In an equation for ‘it’:
it = for' 1 (\ i -> i == 10) (\ i -> i + 1) (print)
*Main>
我不知道怎么了。
答案 0 :(得分:3)
这是你写的:
for' :: a -> (a -> Bool) -> (a -> a ) -> (a -> IO a ) -> IO [a]
for' s cnd incr ioFn = sequenceIO (map (ioFn) ...
*Main> for' 1 (\i->i==10) (\i->i+1) (print )
a (a -> IO ())
------------
() a ~ ()
因此1 :: (Num a) => a ~ (Num ()) => ()
。但是没有Num
类型的()
实例。
这是GHC告诉您的回旋方式,您需要类型为a -> IO a
而不是a -> IO ()
的函数。
Hindley-Milner允许使用“更窄”的类型进行统一,但是如果不是这样,那就更好了-错误消息会更清晰。
在任何情况下,很容易变出自己的值-返回 print ,如
myprint :: a -> IO a
myprint x = do { print x -- or, print x >> return x
; return x
}
答案 1 :(得分:0)
sequenceIO返回类型为IO [a],但ioFn(如for'的定义)为“ print”,返回IO()。您需要ioFn返回IO a,以便sequenceIO的返回将是IO [a]。
例如请尝试“返回”而不是“打印”,然后打印该值。 “返回”是haskell中的一个函数,它仅将传递的参数转换为monad,在这种情况下为IO monad。
main = do p <- for' 1 (\i->i==10) (\i->i+1) (return)
print(p)
这将仅打印1到9个数字的列表。
或
p :: Int -> IO [Int]
p x = for' 1 (\i->i==x) (\i->i+1) (return)
main = do y <- p 10
print (y)