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'はこのスコープで1回だけ発生します。 cpugear.m:078:述語 `cpugear.load_freqs'/ 4の節内: cpugear.m:078:警告:変数`Stream'はこのスコープで1回だけ発生します。
しかし、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:次の場合でもdetを決定できます:
:- 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.