我有下面的演示代码无法编译错误:
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)
除了可疑的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)
是的循环依赖q和q'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)
但我不建议这样做.