奇怪的可能出现在元组类型中

J F*_*sch 0 haskell

我有下面的演示代码无法编译错误:

Occurs check: cannot construct the infinite type: p0 = Maybe p0
    Expected type: PSQ.PSQ (t1, t2, (t0, [a0])) (Maybe p0)
      Actual type: PSQ.PSQ (t1, t2, (t0, [a0])) p0
    In the third argument of `PSQ.insert', namely `q'
    In the expression: PSQ.insert test' time q
Run Code Online (Sandbox Code Playgroud)

如果我从AppendMsg中创建代码的主要编译部分.如果试图使它成为一个单独的函数,它就会失败并出现奇怪的相关错误.我不太确定可能的类型来自哪里.我试图解决它,例如让time = Just (PSQ.lookup test time)但没有快乐.我没有Data.Label /镜头试过它但也没有喜悦.即使是插入附加消息的非常简单的功能也会产生相同的错误.

这可能有什么问题?

import Data.Time
import Data.Time.Clock.POSIX
import qualified Data.PSQueue as PSQ
import Data.Maybe
import Data.Label
import Control.Category
import Prelude hiding ((.))

test = ("192.168.1.1", 3455, (1234566, msgs))
msgs = ["aaa", "bbbb", "ccccc"]

second2 = lens (\(a,b) -> b)   (\b (a,_) -> (a,b))
third3  = lens (\(a,b,c) -> c) (\c (a,b,_) -> (a,b,c))
messages = second2 . third3

append x = modify messages (x :)

newRq = do
      time <- getPOSIXTime
      let q = PSQ.singleton test time
      return q

appendMsg a q = do
      let time = PSQ.lookup test q
      let test' = append a test
      let q' = PSQ.insert test' time q
      let q = PSQ.delete test q' 
      return q

--insertNewRec a q = do 
--     time <- getPOSIXTime
--     let q' = PSQ.insert a time q
--     return q

main :: IO()
main = do
     q <- newRq
     let q' = appendMsg "first" q
     print (q')
Run Code Online (Sandbox Code Playgroud)

根据所有评论/答案修改了appendMsg(见下文).它现在编译但执行以<<loop>>:-(.

appendMsg :: String -> PSQ.PSQ (String, Integer, (Integer, [String])) POSIXTime -> PSQ.
PSQ (String, Integer, (Integer, [String])) POSIXTime 
appendMsg a q = q
      where 
       Just time = PSQ.lookup test q
       test2 = append a test
       q' = PSQ.insert test2 time q
       q = PSQ.delete test q' 
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 5

除了可疑的monadic类型appendMsg,而不是

let time = Just (PSQ.lookup test time)
Run Code Online (Sandbox Code Playgroud)

(顺便说一句.我想第二个'时间'是一个错字,实际上是'q'),你应该试过

let Just time = PSQ.lookup test q
Run Code Online (Sandbox Code Playgroud)

我强烈建议为您的函数提供类型签名,这样GHC可以为您提供更多有用的错误消息,因为类型错误会在它们生成的地方报告,而不是它们导致类型检查失败的地方.

编辑:<<loop>>修改后的代码中的原因

appendMsg :: String -> PSQ.PSQ (String, Integer, (Integer, [String])) POSIXTime
          -> PSQ.PSQ (String, Integer, (Integer, [String])) POSIXTime 
appendMsg a q = q
  where 
   Just time = PSQ.lookup test q
   test2 = append a test
   q' = PSQ.insert test2 time q
   q = PSQ.delete test q'
Run Code Online (Sandbox Code Playgroud)

是的循环依赖qq'where子句英寸 where子句(或let)中的绑定是递归的,可以任意排序,因此qs中的s都是指最后一行中的绑定,而不是参数 - whoops.在原始代码中,您有多个let,因此绑定不是(相互)递归的,并且绑定let x = ...隐藏了标识符的任何先前绑定x.

要打破这个<<loop>>,简单和推荐的修复方法是

  • appendMsg a q = q'' 并在where子句的最后一行 q'' = PSQ.delete test q'
  • appendMsg a q = PSQ.delete test q' 并删除where子句的最后一行

你也可以建一个让塔

appendMsg a q =
    let Just time = ... in
    let test2 = ... in
    let q' = ... in
    let q = ... in q
Run Code Online (Sandbox Code Playgroud)

但我不建议这样做.