如何在 Idris 中使用相互定义的流?
How does one use mutually defined Streams in Idris?
我遇到的问题可能比问题中所述的更普遍。我正在尝试让以下程序运行:
module Main
main: IO ()
process: Int -> Int
process req = req+1
server: Stream Int -> Stream Int
client: Int -> Stream Int -> Stream Int
server (req :: reqs) = process req :: server reqs
client initreq (resp :: resps) = initreq :: client resp resps
mutual
reqsOut: Stream Int
respsOut: Stream Int
-- This fixes the segfault:
-- reqsOut = cycle [1, 2, 3, 4]
reqsOut = client 0 respsOut
respsOut = server reqsOut
main = do
printLn(take 5 reqsOut)
如果我用注释版本替换 reqsOut
的定义,它将 运行,但会按原样生成分段错误。我的猜测是我使用 mutual
不正确,但我不确定如何使用。
请注意,在函数调用中,参数会事先求值,在特定情况下会拆分。在 client
中,流用 client initreq (req :: reqs)
进行大小写拆分,因此 client 0 respsOut
中的 respsOut
在延迟尾部之前得到评估:
reqsOut =
client 0 respsOut =
client 0 (case respsOut of (req :: reqs) => ...) =
client 0 (case (server regsOut) of (req :: regs) => ...) =
...
您可以使用
延迟拆分
client initreq stream = initreq :: client (head stream) (tail stream)
但是你仍然会无限循环 server
:
reqsOut =
client 0 respsOut =
client 0 (server regsOut) =
client 0 (case regsOut of (req :: reqs) => ...) =
...
您可以延迟 respsOut
的计算,方法是使参数 Lazy
:
client : Int -> Lazy (Stream Int) -> Stream Int
client initreq stream = initreq :: client (head stream) (tail stream)
现在 client
终于可以构造一个 Stream Int
而无需评估其参数:
client 0 respsOut =
0 :: Delay (client (head (Force respsOut)) (tail (Force respsOut))) : Stream int
我遇到的问题可能比问题中所述的更普遍。我正在尝试让以下程序运行:
module Main
main: IO ()
process: Int -> Int
process req = req+1
server: Stream Int -> Stream Int
client: Int -> Stream Int -> Stream Int
server (req :: reqs) = process req :: server reqs
client initreq (resp :: resps) = initreq :: client resp resps
mutual
reqsOut: Stream Int
respsOut: Stream Int
-- This fixes the segfault:
-- reqsOut = cycle [1, 2, 3, 4]
reqsOut = client 0 respsOut
respsOut = server reqsOut
main = do
printLn(take 5 reqsOut)
如果我用注释版本替换 reqsOut
的定义,它将 运行,但会按原样生成分段错误。我的猜测是我使用 mutual
不正确,但我不确定如何使用。
请注意,在函数调用中,参数会事先求值,在特定情况下会拆分。在 client
中,流用 client initreq (req :: reqs)
进行大小写拆分,因此 client 0 respsOut
中的 respsOut
在延迟尾部之前得到评估:
reqsOut =
client 0 respsOut =
client 0 (case respsOut of (req :: reqs) => ...) =
client 0 (case (server regsOut) of (req :: regs) => ...) =
...
您可以使用
延迟拆分client initreq stream = initreq :: client (head stream) (tail stream)
但是你仍然会无限循环 server
:
reqsOut =
client 0 respsOut =
client 0 (server regsOut) =
client 0 (case regsOut of (req :: reqs) => ...) =
...
您可以延迟 respsOut
的计算,方法是使参数 Lazy
:
client : Int -> Lazy (Stream Int) -> Stream Int
client initreq stream = initreq :: client (head stream) (tail stream)
现在 client
终于可以构造一个 Stream Int
而无需评估其参数:
client 0 respsOut =
0 :: Delay (client (head (Force respsOut)) (tail (Force respsOut))) : Stream int