我徘徊为什么 Mercury (10.04) 不能推断下一个片段的确定性:
:- pred load_freqs(int::in, io.res(list(float))::out, io::di, io::uo) is det.
load_freqs(CPU, ResFreqs, !IO):-
open_input(cpu_fn(CPU, "available_frequencies"), ResStream, !IO),
(ResStream = io.ok(Stream) ->
ResFreqs = io.ok([])
;ResStream = io.error(Err),
ResFreqs = io.error(Err)
).
它抱怨:
cpugear.m:075: 在 `load_freqs' (in, out, di, uo): cpugear.m:075:错误:不满足确定性声明。 cpugear.m:075:声明为“det”,推断为“semidet”。 cpugear.m:080:“ResStream”和“io.error(Err)”的统一可能会失败。 cpugear.m:076:在谓词“cpugear.load_freqs”/4 的子句中: cpugear.m:076:警告:变量“CPU”在此范围内仅出现一次。 cpugear.m:078:在谓词“cpugear.load_freqs”/4 的子句中: cpugear.m:078:警告:变量“流”在此范围内仅出现一次。
但io.res
只有io.ok/1
和io.error/1
。
下一段代码编译得很好:
:- pred read_freqs(io.res(io.input_stream)::in, io.res(list(float))::out, io::di, io::uo) is det.
read_freqs(io.ok(Stream), io.ok([]), IO, IO).
read_freqs(io.error(Err), io.error(Err), IO, IO).
更新#1:它甚至可以决定:
:- pred read_freqs(bool::in, io.res(io.input_stream)::in, io.res(list(float))::out, io::di, io::uo) is det.
read_freqs(no, ResStream, io.ok([]), IO, IO):- ResStream = io.ok(_).
read_freqs(F, io.ok(_), io.ok([]), IO, IO):- F = yes.
read_freqs(yes, io.error(Err), io.error(Err), IO, IO).
read_freqs(F, ResStream, io.error(Err), IO, IO):- ResStream = io.error(Err), F = no.