関数パラメーター型としてボトム型の使用例はありますか?


12

関数の戻り値の型が⊥(bottom type)の場合、戻り値がないことを意味します。たとえば、どちらもかなり普通の状況で終了またはスローできます。

おそらく、関数にtype型のパラメーターがある場合、(安全に)呼び出すことはできません。そのような関数を定義する理由はありますか?

回答:


17

または空の型の定義プロパティの1つは、すべての型Aに対して関数Aが存在することです。実際、そのような独自の機能が存在します。したがって、この関数を標準ライブラリの一部として提供することはかなり合理的です。多くの場合、それはのようなものと呼ばれます。(サブタイプを有するシステムでは、これが有することによって、単純に扱われるかもしれないすべての型のサブタイプである。次に、暗黙的な変換である。他の関連アプローチはする定義としてα α簡単にすることができ、インスタンス化の任意のタイプです。)Aabsurdabsurd αα

を生成する関数を使用できるようにするため、このような関数または同等の関数が必要です。たとえば、合計タイプE+Aが与えられたとします。私はそれにケースの分析を行うとしてE場合、私は使用して例外をスローするつもりだthrowE。でA場合、私が使用しますfAB。全体的に、タイプB値が必要なので、Bに変えるために何かをする必要があります。それabsurdが私にできることです。

とはいえA独自の関数を定義する理由はそれほど多くありません。定義により、それらは必然的にのインスタンスになりますabsurd。それでも、absurd標準ライブラリによって提供されていない場合、または型チェック/推論を支援するために型に特化したバージョンが必要な場合は、それを行う可能性があります。あなたは、しかし、簡単に終わるだろうな機能を生成することができ、インスタンス化のようなタイプにA

このような関数を記述する理由はあまりありませんが、一般的には許可されます。1つの理由は、コード生成ツール/マクロを簡素化することです。


したがって、これは(x ? 3 : throw new Exception())、分析の目的で、次のようなものに置き換えられるようなものを意味し(x ? 3 : absurd(throw new Exception()))ますか?
bdsl

あなたは、サブタイプまたは定義されていなかった持っていなかった場合はとしてα αの場合、前者はチェックを入力せず、後者は入力します。サブタイピングでは、はい、暗黙的に挿入されます。もちろん、あなたが置くことができるの定義内で効果的に定義するものであるようα αがします。ααabsurdabsurdthrowαα
デレクエルキンスは、

6

関数について言われたことに追加するためabsurd: ⊥ -> aに、この関数が実際に役立つ場所の具体例を示します。

Haskellデータ型Free f aを考えます。これは、s fを含む-形のノードと葉を持つ一般的なツリー構造を表し aます。

data Free f a = Op (f (Free f a)) | Var a

これらのツリーは、次の関数で折りたたむことができます。

fold :: Functor f => (a -> b) -> (f b -> b) -> Free f a -> b
fold gen alg (Var x) = gen x
fold gen alg (Op x) = alg (fmap (fold gen alg) x)

簡単に言うと、この操作algはノードとgenリーフに配置されます。

ここまでで、すべての再帰データ構造は固定小数点データ型を使用して表現できます。Haskellでは、これは(つまり、- 形のノードを持ち、ファンクターの外側に葉がないツリー)Fix fとして定義できます。伝統的に、この構造には次のような折り目があります。type Fix f = Free f ⊥ffcata

cata :: Functor f => (f a -> a) -> Fix f -> a
cata alg x = fold absurd alg x

これは不条理の非常にきちんとした使用を与えます:木には葉がないため(⊥には以外の住民がいないためundefined)、genこのフォールドを使用することは不可能であり、それをabsurd示しています!


2

ボトムタイプは、他のすべてのタイプのサブタイプであり、実際に非常に役立ちます。たとえばNULL、理論的なタイプセーフバージョンのCのの型は、他のすべてのポインター型のサブタイプである必要があります。そうでない場合、たとえばNULL、a char*が期待された場所に戻ることができません。同様に、undefined理論的なタイプセーフJavaScriptの型は、言語の他のすべての型のサブタイプでなければなりません。

exit()throw()IntIntexit()

TST


3
NULL空のタイプである⊥とは異なり、ユニットタイプではありませんか?
bdsl

型理論で≺が何を意味するのかよくわかりません。
bdsl

1
@bdslここでの曲線演算子は「のサブタイプです」です。それが標準かどうかはわかりませんが、私の教授が使ったものです。
ドラコニス

1
@ gnasher729本当ですが、Cも特にタイプセーフではありません。整数をvoid*にキャストできない場合は、任意のポインタ型に使用できる特定の型が必要になると言っています。
ドラコニス

2
ちなみに、サブタイプ関係について私が見た最も一般的な表記は、<:例えばシステムですF<:
デレクエルキンズは

2

私が考えることができる1つの用途があり、それはSwiftプログラミング言語の改善として考えられているものです。

スウィフトはありmaybeモナドが、綴らOptional<T>T?。それと対話する多くの方法があります。

  • 次のような条件付きアンラップを使用できます

    if let nonOptional = someOptional {
        print(nonOptional)
    }
    else {
        print("someOptional was nil")
    }
    
  • を使用してmapflatMap値を変換できます

  • 強制的にアンラップ演算子(!、タイプ(T?) -> T)でコンテンツを強制的にアンラップします。そうでなければ、クラッシュをトリガーします
  • 値を取得するか、デフォルト値を使用するnil-coalescing演算子(??、型(T?, T) -> T):

    let someI = Optional(100)
    print(someI ?? 123) => 100 // "left operand is non-nil, unwrap it.
    
    let noneI: Int? = nil
    print(noneI ?? 123) // => 123 // left operand is nil, take right operand, acts like a "default" value
    

残念ながら、「アンラップまたはエラーをスロー」または「アンラップまたはカスタムエラーメッセージでクラッシュ」と言う簡潔な方法はありませんでした。何かのようなもの

let someI: Int? = Optional(123)
let nonOptionalI: Int = someI ?? fatalError("Expected a non-nil value")

fatalError型を持っているため、コンパイルしません() -> Never()is Void、Swift 'unit type、Neveris Swift's bottom type)。これを呼び出すと、の正しいオペランドとして期待されるものNeverと互換性がTなくなり??ます。

これを改善する試みとして、Swift Evolutionの提案SE-0217-「Unwrap or Die」オペレータが出されました。最終的に拒否されましたがNever、すべてのタイプのサブタイプにすることへの関心が高まりました。

場合はNever、すべての種類のサブタイプとした後、前の例では、コンパイルされます:

let someI: Int? = Optional(123)
let nonOptionalI: Int = someI ?? fatalError("Expected a non-nil value")

の呼び出しサイトに??はタイプがあるため(T?, Never) -> T、これはの(T?, T) -> T署名と互換性があります??


0

Swiftには、「Never」という型があります。これは、ボトム型によく似ています。Neverを返すように宣言された関数は、決して戻りません。

これはプロトコルに関連して便利です。プロトコルには、クラスに特定の関数が必要であるという言語の型システムによる制限がある場合がありますが、この関数を呼び出す必要はなく、引数の型も必要ありませんだろう。

詳細については、swift-evolutionメーリングリストの新しい投稿をご覧ください。


7
「swift-evolutionメーリングリストへの新しい投稿」は、非常に明確または安定したリファレンスではありません。メーリングリストのWebアーカイブはありませんか?
デレクエルキンズは
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.