【问题标题】:Couldn't match expected type ‘IO ()’ with actual type ‘(Controller -> IO ()) -> IO ()’无法将预期类型“IO ()”与实际类型“(Controller -> IO ()) -> IO ()”匹配
【发布时间】:2017-09-16 05:56:37
【问题描述】:

我是 Haskell 的新手,我在尝试配置代码时遇到了这个错误。我知道 main() 中的所有指令都必须是 IO(),并且发生错误是因为我使用的函数之一(在 Graphics.Gloss.Interface.IO.Animate 中)没​​有返回 IO()。我想通过使用光泽包显示遗传算法的结果。 这是我的代码:

module Main where

import Prelude as P
import Control.Monad.Random as Rand
import Data.Functor
import Data.IORef
import Graphics.Gloss.Interface.IO.Animate
import Graphics.Solution
import Graphics.Plot

import Args
import Task
import Parsing
import Genetic

import Control.Concurrent.Async
import Control.Concurrent.STM.TChan
import Control.Monad.STM
import Control.Arrow (first)


main :: IO ()
main = do
  args <- parseOptions 

  opts <- loadEvolOptions (evolOptionsFileName args)
  gen <- newStdGen
  task@(Task _ twrs _ _) <- loadTask (inputFileName args) (fitnessFuncFileName args)

  chan <- newTChanIO
  asolution <- async $ solve chan gen opts task
  dataRef <- newIORef []
  finalSolutionRef <- newIORef Nothing

  animateIO mode white $ const $ do
      mfinsol <- readIORef finalSolutionRef
      case mfinsol of
        Just solution -> do
          samples <- readIORef dataRef
          return $ solutionPicture task solution (fitnessPlot samples)
        Nothing -> do
          msolution <- poll asolution     
          case msolution of
            Nothing -> do
              mv <- atomically $ tryReadTChan chan
              case mv of
                Nothing -> return ()
                Just v -> modifyIORef dataRef (++[v])
              samples <- readIORef dataRef
              return $ fitnessPlot samples
            Just esol -> case esol of
              Left e -> fail $ show e
              Right solution -> do
                saveResult (outputFileName args) (filterTowers solution twrs)
                writeIORef finalSolutionRef (Just solution)
                samples <- readIORef dataRef
                return $ solutionPicture task solution (fitnessPlot samples)
      where mode = InWindow "test_genetic_al" (1280, 1024) (10, 10)
            fitnessPlot ds =  translate (-300) (-200) $ scale 600 600 $ plot "generation" "fitness" $ first fromIntegral <$> ds

这是我得到的:

Couldn't match expected type ‘IO ()’
                with actual type ‘(Controller -> IO ()) -> IO ()’
    In a stmt of a 'do' block:
      animateIO mode white
      $ const
        $ do { mfinsol <- readIORef finalSolutionRef;
               case mfinsol of {
                 Just solution -> do { ... }
                 Nothing -> do { ... } } }
    In the expression:
      do { args <- parseOptions;
           opts <- loadEvolOptions (evolOptionsFileName args);
           gen <- newStdGen;
           task@(Task _ twrs _ _) <- loadTask
                                       (inputFileName args) (fitnessFuncFileName args);
           .... }
    In an equation for ‘main’:
        main
          = do { args <- parseOptions;
                 opts <- loadEvolOptions (evolOptionsFileName args);
                 gen <- newStdGen;
                 .... }
          where
              mode = InWindow "test_genetic_al" (1280, 1024) (10, 10)
              fitnessPlot ds
                = translate (- 300) (- 200)
                  $ scale 600 600
                    $ plot "generation" "fitness" $ first fromIntegral <$> ds

我已经在 Google 和 stackoverflow 上搜索了很多次我的问题,但仍然找不到解决此错误的方法。请帮帮我。

P/S:这是 Graphics.Gloss 的指南:https://hackage.haskell.org/package/gloss-1.11.1.1/docs/Graphics-Gloss-Interface-IO-Animate.html

再次抱歉我的愚蠢问题,在我给出 Lazersmoke 的建议(你可以在下面的评论区看到)之后,我得到了另一个与我要求的错误非常相似的错误:

我改行:animateIO mode white $ const $ do

进入:animateIO模式白(_->return())$const$do

Couldn't match type ‘Picture’ with ‘()’
    Expected type: Controller -> IO ()
      Actual type: Controller -> IO Picture
    In the second argument of ‘($)’, namely
      ‘const
       $ do { mfinsol <- readIORef finalSolutionRef;
              case mfinsol of {
                Just solution -> do { ... }
                Nothing -> do { ... } } }’
    In a stmt of a 'do' block:
      animateIO mode white (\ _ -> return ())
      $ const
        $ do { mfinsol <- readIORef finalSolutionRef;
               case mfinsol of {
                 Just solution -> do { ... }
                 Nothing -> do { ... } } }
    In the expression:
      do { args <- parseOptions;
           opts <- loadEvolOptions (evolOptionsFileName args);
           gen <- newStdGen;
           task@(Task _ twrs _ _) <- loadTask
                                       (inputFileName args) (fitnessFuncFileName args);
           .... }

【问题讨论】:

  • 该错误只是表示您忘记提供一个参数,在这种情况下是Controller -&gt; IO ()函数。
  • 那我该如何解决它,你能告诉我路吗?
  • 他说的,即“回调取显示控制器”。正如您在链接的文档中看到的那样。您需要像 animateIO mode white (\_ -&gt; return ()) $ const $ do 这样的东西来满足该类型,尽管您可能需要根据您的意图提供一个实际的回调以使其正常工作。
  • 更一般地说,我会尝试提取一些函数来使这个块更小和/或添加类型注释以获得更好、更有针对性的错误消息。
  • @ThaoDang,尝试像 Jean-Baptiste 建议的那样将函数拆分为更易于管理的部分,并查看每个部分的类型。特别是,这个最新的错误意味着回调不应该返回 Picture,但 do 块应该以返回单元 (()) 结束。

标签: haskell io controller genetic-algorithm ioerror


【解决方案1】:

animateIO 接受多少个参数?

animateIO :: Display    
          -> Color  
          -> (Float -> IO Picture)  
          -> (Controller -> IO ())  
          -> IO ()

四个。您向animateIO 提供了多少个参数?

animateIO mode white $ …

三个。类型

animateIO mode white $ …

(Controller -&gt; IO ()) -&gt; IO (),这正是您的错误消息告诉您的内容。由于您不想使用Controller -&gt; IO () 部分,您可以提供自己的animateIO

animateIO' :: Display -> Color -> IO Picture -> IO ()
animateIO' m c a = animateIO m c (const a) (const $ return ())

请注意,您的 (\_ -&gt; return ()) 不起作用,因为第三个参数必须生成 Picture,而不是 IO ()

【讨论】:

  • 我会按照您的建议修复我的代码并尽快发布结果,谢谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多