2

すべての整数の定義域が0より大きい関数があるとします。他の入力の結果を未定義にします。簡単にするために、これが増分関数であるとしましょう。Haskellでは、私はこれを次のようなもので達成することができました

f :: Integer -> Integer
f x 
  | x > 0 = x + 1
  | otherwise = undefined

もちろん、この例はかなりわかりやすいですが、私が何を達成したいのかは明確になっているはずです。スキームで同様のことを達成する方法がわかりません。

(define (f x)
  (if (> x 0)
      (+ x 1)
      (?????)))

error私の考えはそこに固執することですが、ハスケルの振る舞いをより厳密に再現する方法はありますか?

4

4 に答える 4

2

あなたの質問は、R5RS(MITスキームが部分的にサポートしていると思いますか?)で、1つのブランチが「未指定の値」を返すことを指摘する回答があるこれに関連しています。したがって、haskell コードに相当するものは次のようになります。if

(define (f x)
  (if (> x 0)
      (+ x 1)))

あなたはおそらくこれをすでに知っています: in haskellundefinedは の観点から定義されてerrorおり、後で削除するプレースホルダーとして主に開発で使用されます。Haskell 関数を定義する適切な方法は、次のような型を与えることですInteger -> Maybe Integer

于 2013-01-01T21:17:09.667 に答える
2

一般的な未定義の値はvoidとして定義され(define void (if #f #f))ます。

于 2013-01-01T23:53:25.600 に答える
1

すべてのScheme実装がif代替部分なしで許可されているわけではないことに注意してください(他の回答で示唆されているように)-たとえば、Racketはこの状況をエラーとしてフラグします。

Racket では(void)、プロシージャが有用な結果を返さないことを明示的に指定することができます (これが MIT スキームで利用可能かどうかを確認してください)。ドキュメントから:

定数#<void>は、副作用があり有用な結果をもたらさないほとんどのフォームおよびプロシージャによって返されます。この定数#<undefined>は、letrec バインディングの初期値として使用されます。#<void>値は常に自分自身に対するものeq?であり、#<undefined>値はeq?自分自身に対するものでもあります。

(void v ...) → void? 定数を返します#<void>。各v引数は無視されます。

つまり、質問の例は次のようになります。

(define (f x)
  (if (> x 0)
      (+ x 1)
      (void)))
于 2013-01-02T02:23:12.307 に答える
0

特に MIT スキームについて言えば、 #!unspecific は代替手段のない if から返される定数だと思います。

(eq? (if (= 1 2) 3) #!unspecific) => #t
于 2013-01-08T23:41:28.277 に答える