Loops Haskell:没有(Num())的实例-定义我自己的一元循环

Loops Haskell:没有(Num())的实例-定义我自己的一元循环,loops,haskell,types,monads,higher-order-functions,Loops,Haskell,Types,Monads,Higher Order Functions,我正在Haskell wiki中尝试此练习: 以下练习结合了您所学到的有关高等教育的知识 顺序函数、递归和I/O。我们将重新创建 在命令式语言中称为for循环。实现一项功能 for :: a -> (a -> Bool) -> (a -> a) -> (a -> IO ()) -> IO () for i p f job = -- ??? 到目前为止,我已经: -- for : init value, end condition function,

我正在Haskell wiki中尝试此练习:

以下练习结合了您所学到的有关高等教育的知识 顺序函数、递归和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))
“的
获取错误:

*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>
'1(\i->i==10)(\i->i+1)(打印)的
*Main>
:323:6:错误:
•没有由文字“1”产生的(Num())实例
•在“for”的第一个参数中,即“1”
在表达式中:对于'1(\i->i==10)(\i->i+1)(打印)
在“it”的方程式中:
它=为'1(\i->i==10)(\i->i+1)(打印)
*Main>

我不知道出了什么问题。

sequenceIO返回类型是IO[a],但ioFn(在for的定义中)是“print”,返回IO()。您需要ioFn来返回IO a,因此sequenceIO的返回将是IO[a]

e、 g.尝试“返回”而不是“打印”,然后打印值。“return”是haskell中的一个函数,它只是将传递的参数转换为monad,在本例中是IO monad

main = do p <- for' 1 (\i->i==10) (\i->i+1) (return) 
         print(p) 
main=dopi==x)(\i->i+1)(返回)
main=do y以下是您所写的内容:

    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::(numa)=>a~(Num())=>()
。但是类型
()
没有
Num
实例

这是GHC迂回的方式告诉您,您需要类型为
a->ioa
的函数,而不是
a->IO()

Hindley Milner允许使用“更窄”的类型进行统一,但在这里,如果不这样做会更好——错误信息会更清楚

在任何情况下,你都很容易想象自己的价值——返回打印,比如


(打印)
的类型是
显示a=>a->IO()
,而不是
显示a=>a->IO a
。您需要将其与其他内容组合以使其返回输入。您的意思是“
ioFn
,它返回
ioa
”。此外,您的缩进错误。您需要更正它,或者添加显式的
{;}
分隔符,或者两者兼而有之。@luqui谢谢;空白是一个重要的工具。也用Lisp。
p :: Int -> IO [Int]
p x =  for' 1 (\i->i==x) (\i->i+1) (return)

main = do y <- p 10
         print (y)  
    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 ~ ()
myprint :: a -> IO a
myprint x = do { print x      -- or,  print x >> return x
               ; return x 
               }