需要帮助消除返回类型的混乱

发布于 2024-12-20 01:57:40 字数 5912 浏览 3 评论 0原文

我的函数太复杂了,我无法明确函数类型应该是什么。我正在努力让 GHC 同意我所期望的就是它所期望的。首先是功能,我认为它应该做什么。然后,混乱就出现了。

flagScheduled ((Left (MkUFD day)):rest) = do
   match <- runDB $ selectList [TestStartDate ==. Just day,
                                TestStatus /<-. [Passed,Failed]] []
   case (L.null match) of
      True -> do
               processedDays <- ([(Left $ MkUFD day)] :) <$> flagScheduled rest
               return processedDays
      False -> do
                let flaggedRange = (calcFlagged match)
                    product      = (testFirmware . snd . P.head) match
                processedDays <- (flagScheduled'
                                  ([(Left $ MkUFD day)] ++
                                   (L.take flaggedRange) rest) (show product) :) <$>
                                   (flagScheduled . L.drop flaggedRange) rest
                return processedDays
flagScheduled ((Right day):rest) = do
     processedDays <- ((Right $ day):) <$> flagScheduled rest
     return processedDays
flagScheduled _ = return []

calcFlagged (( _ ,(Test _ _ (Just startDate) (Just endDate) _ _ )) : rest) =
  fromIntegral $ C.diffDays endDate startDate

flagScheduled' toBeFlagged product =
   L.map (flagIt product) toBeFlagged
    where flagIt product (Left (MkUFD day)) = Right $
                                              MkCal $
                                              Right $
                                              MkUAD $
                                              Left  $
                                               MkSDay day
                                                      (read product :: Product)
                                                      Reserved

我的想法是从 [Either UnFlaggedDay CalendarDay] 开始 我遍历列表,将一些 UnFlaggedDay 转换为 CalendarDay。 其他函数将转换其余的 UnFlaggedDay。下面我定义了我正在使用的类型。

newtype AvailableDay = MkAD (Text, C.Day)
                          deriving (Show, Eq)

newtype UnAvailableDay = MkUAD (Either ScheduledDay Out_Of_Office)
                             deriving Show

data ScheduledDay = MkSDay C.Day Product ScheduledState
                       deriving Show

newtype ReservedDay = MkRDay (C.Day,Product)
                                 deriving (Ord,Show,Eq,Read)

newtype ASAPDay = MkADay (C.Day,Product)
                            deriving (Ord,Show,Eq,Read)

newtype UnFlaggedDay = MkUFD C.Day

newtype CalendarDay = MkCal (Either AvailableDay UnAvailableDay)
                               deriving Show

所以问题是,当我编译时,我得到这个错误,这本身并不令人困惑。

    Utils/BuildDateList.hs:173:44:
        Couldn't match expected type `Either a0 b0'
                    with actual type `[Either UnFlaggedDay CalendarDay]'
        Expected type: GGHandler sub0 master0 monad0 [Either a0 b0]
          Actual type: GGHandler
                         sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]
        In the return type of a call of `flagScheduled'
        In the second argument of `(<$>)', namely `flagScheduled rest'

好吧,看起来我需要做的就是应用一个适当的 concat,然后我就可以创建实际的类型 GGHandler sub0 master0 monad0 [[UnFlaggedDay CalendarDay]] 匹配预期类型GGHandler sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]

但是等等,没那么简单。这是许多尝试之一,无论我将连接放在哪里,它似乎都会导致相同的错误。

   Utils/BuildDateList.hs:164:16:
       Couldn't match expected type `[Either UnFlaggedDay b0]'
                   with actual type `Either UnFlaggedDay b0'
       Expected type: GGHandler
                        sub0 master0 monad0 [[Either UnFlaggedDay b0]]
         Actual type: GGHandler
                        sub0 master0 monad0 [Either UnFlaggedDay b0]
       In the expression: return $ P.concat processedDays
       In the expression:
         do { processedDays <- ([(Left $ MkUFD day)] :)
                             <$>
                               flagScheduled rest;
                return $ P.concat processedDays }

你看到那里发生了什么吗?这是我所做的更改。我将 processedDays 传递给 concat,然后再将其传递给 return

flagScheduled ((Left (MkUFD day)):rest) = do
   match <- runDB $ selectList [TestStartDate ==. Just day,
                                TestStatus /<-. [Passed,Failed]] []
   case (L.null match) of
      True -> do
               processedDays <- ([(Left $ MkUFD day)] :) <$> flagScheduled rest
               return $ P.concat processedDays
      False -> do
                let flaggedRange = (calcFlagged match)
                    product      = (testFirmware . snd . P.head) match
                processedDays <- (flagScheduled'
                                  ([(Left $ MkUFD day)] ++
                                   (L.take flaggedRange) rest) (show product) :) <$>
                                   (flagScheduled . L.drop flaggedRange) rest
                return $ P.concat processedDays
flagScheduled ((Right day):rest) = do
     processedDays <- ((Right $ day):) <$> flagScheduled rest
     return $ P.concat processedDays
flagScheduled _ = return []

因此,事实上,看似简单的更改实际上并非如此,这表明我并不真正了解问题所在。有什么想法吗?

更新:我进行了丹尼尔建议的更改,但收到此错误:

Utils/BuildDateList.hs:169:37:
    Couldn't match expected type `[Either UnFlaggedDay t0]'
                with actual type `Either UnFlaggedDay b0'
    In the first argument of `(++)', namely `(Left $ MkUFD day)'
    In the first argument of `flagScheduled'', namely
      `((Left $ MkUFD day) ++ (P.take flaggedRange) rest)'
    In the first argument of `(:)', namely
      `flagScheduled'
         ((Left $ MkUFD day) ++ (P.take flaggedRange) rest) (show product)'

更新:此问题已解决,只是为了揭示其他(类似)问题。我将采纳这里给出的建议来继续推进。

I have a function too complicated for me to be explicit about what the function type should be. I'm trying to get GHC to agree that what I expect, is what it expects. First, the function, what I think it should be doing. Then, where the confusion comes in.

flagScheduled ((Left (MkUFD day)):rest) = do
   match <- runDB $ selectList [TestStartDate ==. Just day,
                                TestStatus /<-. [Passed,Failed]] []
   case (L.null match) of
      True -> do
               processedDays <- ([(Left $ MkUFD day)] :) <
gt; flagScheduled rest
               return processedDays
      False -> do
                let flaggedRange = (calcFlagged match)
                    product      = (testFirmware . snd . P.head) match
                processedDays <- (flagScheduled'
                                  ([(Left $ MkUFD day)] ++
                                   (L.take flaggedRange) rest) (show product) :) <
gt;
                                   (flagScheduled . L.drop flaggedRange) rest
                return processedDays
flagScheduled ((Right day):rest) = do
     processedDays <- ((Right $ day):) <
gt; flagScheduled rest
     return processedDays
flagScheduled _ = return []

calcFlagged (( _ ,(Test _ _ (Just startDate) (Just endDate) _ _ )) : rest) =
  fromIntegral $ C.diffDays endDate startDate

flagScheduled' toBeFlagged product =
   L.map (flagIt product) toBeFlagged
    where flagIt product (Left (MkUFD day)) = Right $
                                              MkCal $
                                              Right $
                                              MkUAD $
                                              Left  $
                                               MkSDay day
                                                      (read product :: Product)
                                                      Reserved

The idea is I start with a [Either UnFlaggedDay CalendarDay]
I iterate through the list transforming some of the UnFlaggedDays into CalendarDays.
Other functions will transform the rest of the UnFlaggedDays. Below I define the types I am working with.

newtype AvailableDay = MkAD (Text, C.Day)
                          deriving (Show, Eq)

newtype UnAvailableDay = MkUAD (Either ScheduledDay Out_Of_Office)
                             deriving Show

data ScheduledDay = MkSDay C.Day Product ScheduledState
                       deriving Show

newtype ReservedDay = MkRDay (C.Day,Product)
                                 deriving (Ord,Show,Eq,Read)

newtype ASAPDay = MkADay (C.Day,Product)
                            deriving (Ord,Show,Eq,Read)

newtype UnFlaggedDay = MkUFD C.Day

newtype CalendarDay = MkCal (Either AvailableDay UnAvailableDay)
                               deriving Show

So here is the problem, when I compile I get this error, which is not in itself confusing.

    Utils/BuildDateList.hs:173:44:
        Couldn't match expected type `Either a0 b0'
                    with actual type `[Either UnFlaggedDay CalendarDay]'
        Expected type: GGHandler sub0 master0 monad0 [Either a0 b0]
          Actual type: GGHandler
                         sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]
        In the return type of a call of `flagScheduled'
        In the second argument of `(<
gt;)', namely `flagScheduled rest'

Okay fine, it looks like all I need to do is apply a well-placed concat and I can make the actual type GGHandler
sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]

match the expected type GGHandler
sub0 master0 monad0 [[Either UnFlaggedDay CalendarDay]]

But wait, not that simple. Here's one attempt of many, and no matter where I place the concat it seems to lead to the same error.

   Utils/BuildDateList.hs:164:16:
       Couldn't match expected type `[Either UnFlaggedDay b0]'
                   with actual type `Either UnFlaggedDay b0'
       Expected type: GGHandler
                        sub0 master0 monad0 [[Either UnFlaggedDay b0]]
         Actual type: GGHandler
                        sub0 master0 monad0 [Either UnFlaggedDay b0]
       In the expression: return $ P.concat processedDays
       In the expression:
         do { processedDays <- ([(Left $ MkUFD day)] :)
                             <
gt;
                               flagScheduled rest;
                return $ P.concat processedDays }

Did you see what happened there? Here are the changes I made. I passed processedDays to concat before passing it to return.

flagScheduled ((Left (MkUFD day)):rest) = do
   match <- runDB $ selectList [TestStartDate ==. Just day,
                                TestStatus /<-. [Passed,Failed]] []
   case (L.null match) of
      True -> do
               processedDays <- ([(Left $ MkUFD day)] :) <
gt; flagScheduled rest
               return $ P.concat processedDays
      False -> do
                let flaggedRange = (calcFlagged match)
                    product      = (testFirmware . snd . P.head) match
                processedDays <- (flagScheduled'
                                  ([(Left $ MkUFD day)] ++
                                   (L.take flaggedRange) rest) (show product) :) <
gt;
                                   (flagScheduled . L.drop flaggedRange) rest
                return $ P.concat processedDays
flagScheduled ((Right day):rest) = do
     processedDays <- ((Right $ day):) <
gt; flagScheduled rest
     return $ P.concat processedDays
flagScheduled _ = return []

So the fact that what looks like a straight-forward change that isn't, indicates to me that I don't really understand what the problem is. Any ideas?

Update: I made the changes Daniel suggested, but got this error:

Utils/BuildDateList.hs:169:37:
    Couldn't match expected type `[Either UnFlaggedDay t0]'
                with actual type `Either UnFlaggedDay b0'
    In the first argument of `(++)', namely `(Left $ MkUFD day)'
    In the first argument of `flagScheduled'', namely
      `((Left $ MkUFD day) ++ (P.take flaggedRange) rest)'
    In the first argument of `(:)', namely
      `flagScheduled'
         ((Left $ MkUFD day) ++ (P.take flaggedRange) rest) (show product)'

Update: This problem has been solved, only to reveal other (similar) problems. I'm going to take the advice given here to move forward with that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

离线来电— 2024-12-27 01:57:40

第一个嫌疑人:

   case (L.null match) of
      True -> do
           processedDays <- ([(Left $ MkUFD day)] :) <
gt; flagScheduled rest
           return processedDays

也许应该这样写

   case (L.null match) of
      True -> do
           processedDays <- ((Left $ MkUFD day) :) <
gt; flagScheduled rest
           return processedDays

?哦,从编写类型签名开始。这通常会产生更好的错误消息。

The first suspect:

   case (L.null match) of
      True -> do
           processedDays <- ([(Left $ MkUFD day)] :) <
gt; flagScheduled rest
           return processedDays

Maybe that should read

   case (L.null match) of
      True -> do
           processedDays <- ((Left $ MkUFD day) :) <
gt; flagScheduled rest
           return processedDays

? Oh, and start with writing type signatures. That often creates better error messages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文