diff --git a/text-ja/chapter3.md b/text-ja/chapter3.md new file mode 100644 index 00000000..12269aca --- /dev/null +++ b/text-ja/chapter3.md @@ -0,0 +1,858 @@ +# 関数とレコード + +## この章の目標 + +この章では、関数及びレコードというPureScriptプログラムの2つの構成要素を導入します。更に、どのようにPureScriptプログラムを構造化するのか、どのように型をプログラム開発に役立てるかを見ていきます。 + +連絡先のリストを管理する簡単な住所録アプリケーションを作成していきます。 +このコード例により、PureScriptの構文から幾つかの新しい概念を導入します。 + +このアプリケーションのフロントエンドは対話式モードであるPSCiを使うようにしていますが、このコードを土台にJavaScriptでフロントエンドを書くこともできるでしょう。 +実際に後の章で、フォームの検証と保存及び復元の機能を追加します。 + +## プロジェクトの準備 + +この章のソースコードは `src/Data/AddressBook.purs`というファイルに含まれています。 +このファイルは次のようなモジュール宣言とインポート一覧から始まります。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:imports}} +``` + +ここでは、幾つかのモジュールをインポートします。 + +- `Control.Plus`モジュールには`empty`値が定義されています。 +- `Data.List`モジュールは`lists`パッケージで提供されています。 + またこのパッケージはSpagoを使ってインストールできます。 + モジュールには連結リストを使うために必要な幾つかの関数が含まれています。 +- `Data.Maybe`モジュールは、省略可能な値を扱うためのデータ型と関数を定義しています。 + +訳者注:ダブルドット (`..`) を使用すると、 +指定された型コンストラクタのすべてのデータコンストラクタをインポートできます。 + +このモジュールのインポート内容が括弧内で明示的に列挙されていることに注目してください。明示的な列挙はインポート内容の衝突を避けるのに役に立つので、一般に良い習慣です。 + +ソースコードリポジトリをクローンしたと仮定すると、この章のプロジェクトは次のコマンドでSpagoを使用して構築できます。 + +```text +$ cd chapter3 +$ spago build +``` + +## 単純な型 + +JavaScriptの原始型に対応する組み込みデータ型として、PureScriptでは数値型と文字列型、真偽型の3つが定義されています。 +これらは`Prim`モジュールで定義されており、全てのモジュールに暗黙にインポートされます。 +それぞれ`Number`、`String`、`Boolean`と呼ばれており、PSCiで簡単な値の型を表示するのに`:type`コマンドを使うと確認できます。 + +```text +$ spago repl + +> :type 1.0 +Number + +> :type "test" +String + +> :type true +Boolean +``` + +PureScriptには他にも、整数、文字、配列、レコード、関数といった組み込み型が定義されています。 + +小数点以下を省くと整数になり、型 `Number`の浮動小数点数の値と区別されます。 + +```text +> :type 1 +Int +``` + +二重引用符を使用する文字列直値とは異なり、文字直値は一重引用符で囲みます。 + +```text +> :type 'a' +Char +``` + +配列はJavaScriptの配列に対応していますが、JavaScriptの配列とは異なり、PureScriptの配列の全ての要素は同じ型を持つ必要があります。 + +```text +> :type [1, 2, 3] +Array Int + +> :type [true, false] +Array Boolean + +> :type [1, false] +Could not match type Int with type Boolean. +``` + +最後の例は型検証器によるエラーを示しています。 +配列の2つの要素の型を*単一化*(つまり等価にする意)するのに失敗したのです。 + +レコードはJavaScriptのオブジェクトに対応しており、レコード直値はJavaScriptのオブジェクト直値と同じ構文になっています。 + +```text +> author = { name: "Phil", interests: ["Functional Programming", "JavaScript"] } + +> :type author +{ name :: String +, interests :: Array String +} +``` + +この型が示しているのは指定されたオブジェクトが2つの*フィールド*を持っているということです。 +それぞれ`String`型のフィールド`name`と`Array +String`型のフィールド`interests`で、後者は`String`の配列ということです。 + +ドットに続けて参照したいフィールドのラベルを書くとレコードのフィールドを参照できます。 + +```text +> author.name +"Phil" + +> author.interests +["Functional Programming","JavaScript"] +``` + +PureScriptの関数はJavaScriptの関数に対応しています。PureScriptの標準ライブラリは多くの関数の例を提供しており、この章ではそれらをもう少し詳しく見ていきます。 + +```text +> import Prelude +> :type flip +forall a b c. (a -> b -> c) -> b -> a -> c + +> :type const +forall a b. a -> b -> a +``` + +ファイルのトップレベルでは、等号の直前に引数を指定することで関数を定義できます。 + +```haskell +add :: Int -> Int -> Int +add x y = x + y +``` + +代えて、バックスラッシュ文字に続けて空白文字で区切られた引数名のリストを書くことで、関数をインラインでも定義できます。 +PSCiで複数行の宣言を入力するには、`:paste`コマンドを使用して「貼り付けモード」に入ります。 +このモードでは、*Control-D*キーシーケンスを使って宣言を終了します。 + +```text +> :paste +… add :: Int -> Int -> Int +… add = \x y -> x + y +… ^D +``` + +PSCiでこの関数が定義されていると、次のように関数の隣に2つの引数を空白で区切って書くことで、関数をこれらの引数に*適用* (apply) できます。 + +```text +> add 10 20 +30 +``` + +## 量化された型 + +前の節ではPreludeで定義された関数の型を幾つか見てきました。 +例えば`flip`関数は次のような型を持っていました。 + +```text +> :type flip +forall a b c. (a -> b -> c) -> b -> a -> c +``` + +この`forall`キーワードは、`flip`が*全称量化された型*を持つことを示しています。 +つまり`a`や`b`や`c`をどの型に置き換えても良く、`flip`はその型で動作するのです。 + +例えば、`a`を`Int`、`b`を`String`、`c`を`String`と選んだとします。 +その場合、`flip`の型を次のように*特殊化*できます。 + +```text +(Int -> String -> String) -> String -> Int -> String +``` + +量化された型を特殊化したいということをコードで示す必要はありません。 +特殊化は自動的に行われます。 +例えば、あたかも既にその型の`flip`を持っていたかのように、`flip`を使えます。 + +```text +> flip (\n s -> show n <> s) "Ten" 10 + +"10Ten" +``` + +`a`、`b`、`c`の型はどんな型でも選べるといっても、一貫していなければなりません。 +`flip`に渡す関数の型は他の引数の型と整合性がなくてはなりません。 +第2引数として文字列`"Ten"`、第3引数として数`10`を渡したのはそれが理由です。 +もし引数が逆になっているとうまくいかないでしょう。 + +```text +> flip (\n s -> show n <> s) 10 "Ten" + +Could not match type Int with type String +``` + +## 字下げについての注意 + +PureScriptのコードは字下げの大きさに意味があります。ちょうどHaskellと同じで、JavaScriptとは異なります。コード内の空白の多寡は無意味ではなく、Cのような言語で中括弧によってコードのまとまりを示しているように、PureScriptでは空白がコードのまとまりを示すために使われているということです。 + +宣言が複数行にわたる場合は、最初の行以外は最初の行の字下げより深くしなければなりません。 + +したがって、次は正しいPureScriptコードです。 + +```haskell +add x y z = x + + y + z +``` + +しかし、次は正しいコードではありません。 + +```haskell +add x y z = x + +y + z +``` + +後者では、PureScriptコンパイラはそれぞれの行ごとに1つ、つまり*2つ*の宣言であると構文解析します。 + +一般に、同じブロック内で定義された宣言は同じ深さで字下げする必要があります。 +例えばPSCiでlet文の宣言は同じ深さで字下げしなければなりません。 +次は正しいコードです。 + +```text +> :paste +… x = 1 +… y = 2 +… ^D +``` + +しかし、これは正しくありません。 + +```text +> :paste +… x = 1 +… y = 2 +… ^D +``` + +PureScriptの幾つかの予約語(例えば `where`や `of`、 +`let`)は新たなコードのまとまりを導入しますが、そのコードのまとまり内の宣言はそれより深く字下げされている必要があります。 + +```haskell +example x y z = foo + bar + where + foo = x * y + bar = y * z +``` + +ここで `foo`や `bar`の宣言は `example`の宣言より深く字下げされていることに注意してください。 + +ただし、ソースファイルの先頭、最初の `module`宣言における予約語 `where`だけは、この規則の唯一の例外になっています。 + +## 独自の型の定義 + +PureScriptで新たな問題に取り組むときは、まずはこれから扱おうとする値の型の定義を書くことから始めるのがよいでしょう。最初に、住所録に含まれるレコードの型を定義してみます。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:Entry}} +``` + +これは`Entry`という*型同義語*を定義しています。 +型`Entry`は等号の右辺と等価ということです。 +レコードの型は`firstName`、`lastName`、`phone`という3つのフィールドからなります。 +2つの名前のフィールドは型`String`を持ち、`address`は以下で定義された型`Address`を持ちます。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:Address}} +``` + +なお、レコードには他のレコードを含めることができます。 + +それでは、住所録のデータ構造として3つめの型同義語も定義してみましょう。 +単に項目の連結リストとして表すことにします。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:AddressBook}} +``` + +なお、`List Entry`は `Array Entry`とは同じではありません。 +後者は項目の*配列*を表しています。 + +## 型構築子と種 + +`List`は*型構築子*(type constructor、型コンストラクタ)の一例になっています。`List`そのものは型ではなく、何らかの型 +`a`があるとき `List a`が型になっています。つまり、 `List`は _型引数_ (type argument) `a`をとり、新たな型 +`List a`を _構築_ するのです。 + +なお、ちょうど関数適用と同じように、型構築子は他の型に並置するだけで適用されます。 +実際、型`List Entry`は型構築子`List`が型`Entry`に*適用*されたもので、項目のリストを表しています。 + +もし間違って(型注釈演算子 `::`を使って)型 `List`の値を定義しようとすると、今まで見たことのない種類のエラーが表示されるでしょう。 + +```text +> import Data.List +> Nil :: List +In a type-annotated expression x :: t, the type t must have kind Type +``` + +これは*種エラー*です。値がその*型*で区別されるのと同じように、型はその*種*によって区別されます。間違った型の値が*型エラー*になるように、*間違った種*の型は*種エラー*を引き起こします。 + +`Number`や `String`のような、値を持つ全ての型の種を表す `Type`と呼ばれる特別な種があります。 + +型構築子にも種があります。 +例えば種 `Type -> Type`はちょうど `List`のような型から型への関数を表しています。 +ここでエラーが発生したのは、値が種 `Type`であるような型を持つと期待されていたのに、 `List`は種 `Type -> Type`を持っているためです。 + +PSCiで型の種を調べるには、 `:kind`命令を使用します。例えば次のようになります。 + +```text +> :kind Number +Type + +> import Data.List +> :kind List +Type -> Type + +> :kind List String +Type +``` + +PureScriptの _種システム_ は他にも面白い種に対応していますが、それらについては本書の他の部分で見ていくことになるでしょう。 + +## 住所録の項目の表示 + +それでは最初に、文字列で住所録の項目を表現する関数を書いてみましょう。 +まずは関数に型を与えることから始めます。 +型の定義は省略できますが、ドキュメントとしても役立つので型を書いておくようにすると良いでしょう。 +実際、トップレベルの宣言に型註釈が含まれていないと、PureScriptコンパイラが警告を出します。 +型宣言は関数の名前とその型を `::`記号で区切るようにして書きます。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:showEntry_signature}} +``` + +この型シグネチャが言っているのは、`showEntry`は引数として`Entry`を取り`String`を返す関数であるということです。 +以下は`showEntry`のコードです。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:showEntry_implementation}} +``` + +この関数は`Entry`レコードの3つのフィールドを連結し、単一の文字列にします。 +ここで使用される`showAddress`関数は`address`フィールド中のレコードを文字列に変えます。 +`showAddress`の定義は次の通りです。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:showAddress}} +``` + +関数定義は関数の名前で始まり、引数名のリストが続きます。関数の結果は等号の後ろに定義します。フィールドはドットに続けてフィールド名を書くことで参照できます。PureScriptでは、文字列連結はJavaScriptのような単一のプラス記号ではなく、ダイアモンド演算子(`<>`)を使用します。 + +## はやめにテスト、たびたびテスト + +PSCi対話式モードでは反応を即座に得られるので、素早い試作開発に向いています。 +それではこの最初の関数が正しく動作するかをPSCiを使用して確認してみましょう。 + +まず、これまでに書いたコードをビルドします。 + +```text +$ spago build +``` + +次に、PSCiを起動し、この新しいモジュールをインポートするために `import`命令を使います。 + +```text +$ spago repl + +> import Data.AddressBook +``` + +レコード直値を使うと、住所録の項目を作成できます。レコード直値はJavaScriptの無名オブジェクトと同じような構文で名前に束縛します。 + +```text +> address = { street: "123 Fake St.", city: "Faketown", state: "CA" } +``` + +それでは、この例に関数を適用してみてください。 + +```text +> showAddress address + +"123 Fake St., Faketown, CA" +``` + +`showEntry`も、住所の例を含む住所録項目レコードを作って試しましょう。 + +```text +> entry = { firstName: "John", lastName: "Smith", address: address } +> showEntry entry + +"Smith, John: 123 Fake St., Faketown, CA" +``` + +## 住所録の作成 + +今度は住所録を扱う補助関数を幾つか書いてみましょう。 +空の住所録を表す値が必要ですが、これは空のリストです。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:emptyBook}} +``` + +既存の住所録に値を挿入する関数も必要でしょう。この関数を `insertEntry`と呼ぶことにします。関数の型を与えることから始めましょう。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:insertEntry_signature}} +``` + +この型シグネチャに書かれているのは、最初の引数として`Entry`、第2引数として`AddressBook`を取り、新しい`AddressBook`を返すということです。 + +既存の`AddressBook`を直接変更することはしません。 +代わりに、同じデータが含まれている新しい`AddressBook`を返します。 +このように`AddressBook`は*不変データ構造*の一例となっています。 +これはPureScriptにおける重要な考え方です。 +変更はコードの副作用であり、効率良く挙動を探る上で妨げになります。 +そのため可能な限り純粋関数や不変なデータにする方が好ましいのです。 + +`insertEntry`を実装するのに`Data.List`の`Cons`関数が使えます。 +この関数の型を見るには、PSCiを起動し `:type`コマンドを使います。 + +```text +$ spago repl + +> import Data.List +> :type Cons + +forall a. a -> List a -> List a +``` + +この型シグネチャで書かれているのは、`Cons`が何らかの型`a`の値と型`a`の要素のリストを取り、同じ型の項目を持つ新しいリストを返すということです。 +`a`を`Entry`型として特殊化してみましょう。 + +```haskell +Entry -> List Entry -> List Entry +``` + +しかし、 `List Entry`はまさに `AddressBook`ですから、次と同じになります。 + +```haskell +Entry -> AddressBook -> AddressBook +``` + +今回の場合、既に適切な入力があります。 +`Entry`と `AddressBook`に `Cons`を適用すると、新しい `AddressBook`を得ることができます。 +これこそがまさに求めていた関数です。 + +`insertEntry`の実装は次のようになります。 + +```haskell +insertEntry entry book = Cons entry book +``` + +こうすると、等号の左側にある2つの引数`entry`と`book`がスコープに導入されます。 +それから`Cons`関数を適用し、結果を作成しています。 + +## カリー化された関数 + +PureScriptでは、関数は常に1つの引数だけを取ります。 +`insertEntry`関数は2つの引数を取るように見えますが、*カリー化された関数*の一例なのです。 + +`insertEntry`の型に含まれる `->`は右結合の演算子であり、つまりこの型はコンパイラによって次のように解釈されます。 + +```haskell +Entry -> (AddressBook -> AddressBook) +``` + +すなわち、`insertEntry`は関数を返す関数なのです。 +この関数は単一の引数`Entry`を取り、新しい関数を返します。 +今度はこの関数が単一の引数`AddressBook`を取り、新しい`AddressBook`を返します。 + +これはつまり、最初の引数だけを与えて`insertEntry`を*部分適用*できたりするということです。 +PSCiで結果の型が見られます。 + +```text +> :type insertEntry entry + +AddressBook -> AddressBook +``` + +期待した通り、戻り値の型は関数になっていました。 +この結果の関数に2つ目の引数も適用できます。 + +```text +> :type (insertEntry entry) emptyBook +AddressBook +``` + +ただし、ここでの括弧は不要です。 +以下は等価です。 + +```text +> :type insertEntry entry emptyBook +AddressBook +``` + +これは関数適用が左に結合するためで、なぜ空白で区切った引数を次々に関数に指定するだけでいいのかの説明にもなっています。 + +関数の型の`->`演算子は関数の*型構築子*です。 +この演算子は2つの型引数を取ります。 +左右の被演算子はそれぞれ関数の引数の型と返り値の型です。 + +本書では今後、「2引数の関数」というように表現することがあることに注意してください。 +しかしそれはカリー化された関数を意味していると考えるべきで、その関数は最初の引数を取り2つ目の引数を取る別の関数を返すのです。 + +今度は `insertEntry`の定義について考えてみます。 + +```haskell +insertEntry :: Entry -> AddressBook -> AddressBook +insertEntry entry book = Cons entry book +``` + +もし式の右辺に明示的に括弧をつけるなら、`(Cons entry) book`となります。 +つまり`insertEntry entry`はその引数が単に関数`(Cons entry)`に渡されるような関数だということです。 +ところがこの2つの関数はどんな入力についても同じ結果を返すので、となると同じ関数ではないですか。 +よって、両辺から引数`book`を削除できます。 + +```haskell +insertEntry :: Entry -> AddressBook -> AddressBook +insertEntry entry = Cons entry +``` + +しかし今や同様の議論により、両辺から `entry`も削除できます。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:insertEntry}} +``` + +この処理は*イータ変換*と呼ばれ、(その他の技法を併用して)*ポイントフリー形式*へと関数を書き換えるのに使えます。 +つまり、引数を参照せずに関数を定義できるのです。 + +`insertEntry`の場合、イータ変換によって「`insertEntry`は単にリストにおけるconsだ」となり、とても明快な関数の定義になりました。 +しかし、一般にポイントフリー形式のほうがいいのかどうかには議論の余地があります。 + +## プロパティ取得子 + +よくあるパターンの1つとして、レコード中の個別のフィールド(または「プロパティ」)を取得することがあります。 +`Entry`から`Address`を取り出すインライン関数は次のように書けます。 + +```haskell +\entry -> entry.address +``` + +PureScriptでは[_プロパティ取得子_](https://github.com/purescript/documentation/blob/master/language/Syntax.md#property-accessors)という略記が使えます。この略記では下線文字は無名関数の引数として振舞うため、上記のインライン関数は次と等価です。 + +```haskell +_.address +``` + +これは何段階のプロパティでも動くため、`Entry`に関連する街を取り出す関数は次のように書けます。 + +```haskell +_.address.city +``` + +以下は一例です。 + +```text +> address = { street: "123 Fake St.", city: "Faketown", state: "CA" } +> entry = { firstName: "John", lastName: "Smith", address: address } +> _.lastName entry +"Smith" + +> _.address.city entry +"Faketown" +``` + +## 住所録に問い合わせる + +最小限の住所録アプリケーションの実装で必要になる最後の関数は、名前で人を検索し適切な`Entry`を返すものです。 +これは小さな関数を組み合わせることでプログラムを構築するという、関数型プログラミングで鍵となる考え方のよい応用例になるでしょう。 + +住所録を絞り込めば該当する姓名を持つ項目だけを保持するようにできます。 +そうすれば結果のリストの先頭(つまり最初)の要素を返せます。 + +この大まかな道筋の仕様があれば関数の型を計算できます。 +まずPSCiを開いて`filter`関数と`head`関数の型を探してみましょう。 + +```text +$ spago repl + +> import Data.List +> :type filter + +forall a. (a -> Boolean) -> List a -> List a + +> :type head + +forall a. List a -> Maybe a +``` + +型の意味を理解するために、これらの2つの型の一部を取り出してみましょう。 + +`filter`は2引数のカリー化された関数です。 +最初の引数は関数で、リストの要素を取り`Boolean`値を返します。 +第2引数は要素のリストで、返り値は別のリストです。 + +`head`は引数としてリストを取り、 `Maybe a`という今までに見たことがない型を返します。 +`Maybe +a`は型`a`の省略可能な値を表しており、JavaScriptのような言語で値がないことを示すための`null`を使う代わりとなる、型安全な代替を提供します。 +後の章で改めて詳しく見ていきます。 + +`filter`と `head`の全称量化された型は、PureScriptコンパイラによって次のように _特殊化_ (specialized) +されます。 + +```haskell +filter :: (Entry -> Boolean) -> AddressBook -> AddressBook + +head :: AddressBook -> Maybe Entry +``` + +関数の引数として姓名を渡す必要があるだろうということは分かっています。 + +`filter`に渡す関数も必要になることもわかります。この関数を `filterEntry`と呼ぶことにしましょう。 `filterEntry`は `Entry -> Boolean`という型を持っています。 `filter filterEntry`という関数適用の式は、 `AddressBook -> AddressBook`という型を持つでしょう。もしこの関数の結果を `head`関数に渡すと、型 `Maybe Entry`の結果を得ることになります。 + +これまでのことを纏めると、関数の妥当な型シグネチャは次のようになります。`findEntry`と呼ぶことにしましょう。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:findEntry_signature}} +``` + +この型シグネチャで書かれているのは、`findEntry`が姓と名前の2つの文字列及び`AddressBook`を引数に取り、省略可能な`Entry`を返すということです。 +省略可能な結果は名前が住所録に見付かった場合にのみ値を持ちます。 + +そして、 `findEntry`の定義は次のようになります。 + +```haskell +findEntry firstName lastName book = head (filter filterEntry book) + where + filterEntry :: Entry -> Boolean + filterEntry entry = entry.firstName == firstName && entry.lastName == lastName +``` + +一歩ずつこのコードを調べてみましょう。 + +`findEntry`は、どちらも文字列型である `firstName`と `lastName`、`AddressBook`型の +`book`という3つの名前をスコープに導入します。 + +定義の右辺では`filter`関数と`head`関数が組み合わさっています。 +まず項目のリストを絞り込み、その結果に`head`関数を適用しています。 + +真偽型を返す関数 `filterEntry`は `where`節の内部で補助的な関数として定義されています。 +このため、 `filterEntry`関数はこの定義の内部では使用できますが、外部では使用できません。 +また、`filterEntry`はそれを包む関数の引数に依存でき、 `filterEntry`は指定された `Entry`を絞り込むために引数 +`firstName`と `lastName`を使用しているので、 `filterEntry`が +`findEntry`の内部にあることは必須になっています。 + +なお、最上位での宣言と同じように、必ずしも`filterEntry`の型シグネチャを指定しなくても構いません。 +ただし、ドキュメントの一形態として指定しておくことが推奨されます。 + +## 中置の関数適用 + +これまでお話しした関数のほとんどは*前置*関数適用でした。 +関数名が引数の*前*に置かれていたということです。 +例えば`insertEntry`関数を使って`Entry` (`john`) を空の`AddressBook`に追加する場合、以下のように書けます。 + +```haskell +> book1 = insertEntry john emptyBook +``` + +しかし本章には*中置*[2引数演算子](https://github.com/purescript/documentation/blob/master/language/Syntax.md#binary-operators)の例も含まれています。 +例えば`filterEntry`の定義中の`==`演算子で、2つの引数の*間*に置かれています。 +PureScriptのソースコードでこうした中置演算子は隠れた*前置*の実装への中置別称として定義されています。 +例えば`==`は以下の行により前置の`eq`関数の中置別称として定義されています。 + +```haskell +infix 4 eq as == +``` + +したがって`filterEntry`中の`entry.firstName == firstName`は`eq entry.firstName +firstName`で置き換えられます。 +この節の後のほうで中置演算子を定義する例にもう少し触れます。 + +前置関数を演算子としての中置の位置に置くと、より読みやすいコードになる場面があります。 +その一例が`mod`関数です。 + +```text +> mod 8 3 +2 +``` + +上の用例でも充分動作しますが、読みにくいです。 +より馴染みのある表現の仕方は「8 mod 3」です。 +バックスラッシュ (\`) の中に前置関数を包むとそのように書けます。 + +```text +> 8 `mod` 3 +2 +``` + +同様に、`insertEntry`をバックスラッシュで包むと中置演算子に変わります。 +例えば以下の`book1`と`book2`は等価です。 + +```haskell +book1 = insertEntry john emptyBook +book2 = john `insertEntry` emptyBook +``` + +複数回`insertEntry`を適用することで複数の項目がある`AddressBook`を作ることができますが、以下のように前置関数 +(`book3`) として適用するか中置演算子 (`book4`) として適用するかの2択があります。 + +```haskell +book3 = insertEntry john (insertEntry peggy (insertEntry ned emptyBook)) +book4 = john `insertEntry` (peggy `insertEntry` (ned `insertEntry` emptyBook)) +``` + +`insertEntry`には中置演算子別称(または同義語)も定義できます。 +この演算子の名前に適当に`++`を選び、[優先度](https://github.com/purescript/documentation/blob/master/language/Syntax.md#precedence)を`5`にし、そして`infixr`を使って右[結合](https://github.com/purescript/documentation/blob/master/language/Syntax.md#associativity)とします。 + +```haskell +infixr 5 insertEntry as ++ +``` + +この新しい演算子で上の`book4`の例を次のように書き直せます。 + +```haskell +book5 = john ++ (peggy ++ (ned ++ emptyBook)) +``` + +新しい`++`演算子の右結合性により、意味を変えずに括弧を除去できます。 + +```haskell +book6 = john ++ peggy ++ ned ++ emptyBook +``` + +括弧を消去する他のよくある技法は、いつもの前置関数と一緒に`apply`の中置演算子`$`を使うというものです。 + +例えば前の`book3`の例は以下のように書き直せます。 + +```haskell +book7 = insertEntry john $ insertEntry peggy $ insertEntry ned emptyBook +``` + +括弧を`$`で置き換えるのは大抵入力しやすくなりますし(議論の余地がありますが)読みやすくなります。 +この記号の意味を覚えるための記憶術として、ドル記号を2つの括弧に打ち消し線が引かれたものと見ることで、これで括弧が不必要になったのだと推測できるという方法があります。 + +なお、`($)`は言語にハードコードされた特別な構文ではありません。 +単に`apply`という名前の普通の関数のための中置演算子であって、`Data.Function`で以下のように定義されています。 + +```haskell +apply :: forall a b. (a -> b) -> a -> b +apply f x = f x + +infixr 0 apply as $ +``` + +`apply`関数は、他の関数(型は`(a -> b)`)を最初の引数に、値(型は`a`)を2つ目の引数に取って、その値に対して関数を呼びます。 +この関数が何ら意味のあることをしていないようだと思ったら、全くもって正しいです。 +この関数がなくてもプログラムは論理的に同一です([参照透過性](https://en.wikipedia.org/wiki/Referential_transparency)も見てください)。 +この関数の構文的な利便性はその中置演算子に割り当てられた特別な性質からきています。 +`$`は右結合 (`infixr`) で低い優先度 (`0`) の演算子ですが、これにより深い入れ子になった適用から括弧の束を削除できるのです。 + +さらなる`$`演算子を使った括弧退治のチャンスは以前の`findEntry`関数にあります。 + +```haskell +findEntry firstName lastName book = head $ filter filterEntry book +``` + +この行をより簡潔に書き換える方法を次節の「関数合成」で見ていきます。 + +名前の短い中置演算子を前置関数として使いたければ括弧で囲むことができます。 + +```text +> 8 + 3 +11 + +> (+) 8 3 +11 +``` + +その代わりの手段として演算子は部分適用でき、これには式を括弧で囲んで[演算子節](https://github.com/purescript/documentation/blob/master/language/Syntax.md#operator-sections)中の引数として`_`を使います。これは簡単な無名関数を作るより便利な方法として考えることができます(以下の例ではそこから無名関数を名前に束縛しているので、もはや別に無名とも言えなくなっていますが)。 + +```text +> add3 = (3 + _) +> add3 2 +5 +``` + +纏めると、以下は引数に`5`を加える関数の等価な定義です。 + +```haskell +add5 x = 5 + x +add5 x = add 5 x +add5 x = (+) 5 x +add5 x = 5 `add` x +add5 = add 5 +add5 = \x -> 5 + x +add5 = (5 + _) +add5 x = 5 `(+)` x -- よおポチ、中置に目がないっていうから、中置の中に中置を入れといたぜ +``` + +## 関数合成 + +イータ変換を使うと `insertEntry`関数を簡略化できたのと同じように、引数をよく考察すると `findEntry`の定義を簡略化できます。 + +なお、引数 `book`は関数 `filter filterEntry`に渡され、この適用の結果が `head`に渡されます。これは言いかたを変えれば、 +`filter filterEntry`と `head`の _合成_ (composition) に `book`が渡されるということです。 + +PureScriptの関数合成演算子は `<<<`と `>>>`です。前者は「逆方向の合成」であり、後者は「順方向の合成」です。 + +何れかの演算子を使用して `findEntry`の右辺を書き換えることができます。 +逆順の合成を使用すると、右辺は次のようになります。 + +```haskell +(head <<< filter filterEntry) book +``` + +この形式なら最初の定義にイータ変換の技を適用でき、 `findEntry`は最終的に次のような形式に到達します。 + +```haskell +{{#include ../exercises/chapter3/src/Data/AddressBook.purs:findEntry_implementation}} + ... +``` + +右辺を次のようにしても同じく妥当です。 + +```haskell +filter filterEntry >>> head +``` + +どちらにしても、これは「`findEntry`は絞り込み関数と`head`関数の合成である」という +`findEntry`関数のわかりやすい定義を与えます。 + +どちらの定義のほうが分かりやすいかの判断はお任せしますが、このように関数を部品として捉えるとしばしば有用です。 +各関数は1つの役目をこなすようにし、解法を関数合成を使って組み立てるのです。 + +## 演習 + + 1. (簡単)`findEntry`関数の定義の主な部分式の型を書き下し、 `findEntry`関数についてよく理解しているか試してみましょう。 + 例えば`findEntry`の定義の中にある `head`関数の型は `AddressBook -> Maybe + Entry`と特殊化されています。 + *補足*:この問題にはテストがありません。 + 1. (普通)関数`findEntryByStreet :: String -> AddressBook -> Maybe + Entry`を書いてください。 + この関数は与えられた通りの住所から`Entry`を見付け出します。 + *手掛かり*:`findEntry`にある既存のコードを再利用してください。 + 実装した関数をPSCiと`spago test`を走らせてテストしてください。 + 1. (普通)`filterEntry`を(`<<<`や`>>>`を使った)合成で置き換えて、`findEntryByStreet`を書き直してください。 + 合成の対象は、プロパティ取得子(`_.`記法を使います)と、与えられた文字列引数が与えられた通りの住所に等しいかを判定する関数です。 + 1. (普通)名前が`AddressBook`に存在するかどうかを調べて真偽値で返す関数`isInBook`を書いてみましょう。 + *手掛かり*:PSCiを使って`Data.List.null`関数の型を見付けてください。 + この関数はリストが空かどうかを調べます。 + 1. (難しい)「重複」している住所録の項目を削除する関数`removeDuplicates`を書いてみましょう。 + 項目が同じ姓名を共有していれば`address`フィールドに関係なく、項目が重複していると考えます。 + *手掛かり*:`Data.List.nubByEq`関数の型をPSCiを使って調べましょう。 + この関数は等価性の述語に基づいてリストから重複要素を削除します。 + なお、それぞれの重複する項目の集合において最初の要素(リストの先頭に最も近い)が保持する項目です。 + +## まとめ + +この章では関数型プログラミングの新しい概念を幾つか押さえ、以下の方法を学びました。 + +- 対話的モードのPSCiを使用して、関数で実験したり思いついたことを試したりする。 +- 正確さのための道具として、また実装のための道具として型を使う。 +- 多引数の関数を表現するためにカリー化された関数を使う。 +- 合成により小さな部品からプログラムを作る。 +- `where`式を使ってコードを手際良く構造化する。 +- `Maybe`型を使用してnull値を回避する。 +- イータ変換や関数合成のような技法を使ってより分かりやすい仕様にリファクタする。 + +次の章からは、これらの考えかたに基づいて進めていきます。 diff --git a/translation/ja.po b/translation/ja.po index f4975cda..497155ed 100644 --- a/translation/ja.po +++ b/translation/ja.po @@ -16,7 +16,7 @@ msgid "" msgstr "" "Project-Id-Version: com.github.gemmaro.purescript-book.v0.1.0\n" "POT-Creation-Date: 2023-07-10 21:30+0900\n" -"PO-Revision-Date: 2023-07-12 08:37+0900\n" +"PO-Revision-Date: 2023-07-14 21:38+0900\n" "Last-Translator: gemmaro \n" "Language-Team: none\n" "Language: ja\n" @@ -8484,20 +8484,14 @@ msgstr "{{#include ../exercises/chapter11/src/Game.purs:pickup_case}}\n" #. type: Plain text #: text/chapter11.md:803 #, fuzzy -#| msgid "" -#| "The `lookup` function returns an optional result indicated by the `Maybe` " -#| "type constructor. If the key does not appear in the map, the `lookup` " -#| "function returns `Nothing`, otherwise it returns the corresponding value " -#| "in the `Just` constructor." msgid "" "The `lookup` function returns an optional result indicated by the `Maybe` " "type constructor. If the key does not appear in the map, the `lookup` " "function returns `Nothing`; otherwise, it returns the corresponding value in " "the `Just` constructor." msgstr "" -"`lookup`関数は `Maybe`型構築子で示されたオプショナルな結果を返します。\n" -"`lookup`関数は、キーがマップにない場合は `Nothing`を返し、それ以外の場合は " -"`Just`構築子で対応する値を返します。" +"`lookup`関数は `Maybe`型構築子で示された省略可能な結果を返します。\n" +"`lookup`関数は、キーがマップにない場合は `Nothing`を返し、それ以外の場合は `Just`構築子で対応する値を返します。" #. type: Plain text #: text/chapter11.md:805 @@ -11453,7 +11447,7 @@ msgid "" "This approach is taken in the `drawing` package, and it brings the " "flexibility of manipulating the scene as data in various ways before " "rendering." -msgstr "この手法は `drawing`パッケージでも採用されており、描画前にさまざまな方法でデータとしてシーンを操作できる柔軟性を齎しています。" +msgstr "この手法は `drawing`パッケージでも採用されており、描画前に様々な方法でデータとしてシーンを操作できる柔軟性を齎しています。" #. type: Plain text #: text/chapter12.md:612 @@ -14777,12 +14771,6 @@ msgstr "" #. type: Plain text #: text/chapter14.md:580 #, fuzzy -#| msgid "" -#| "Suppose we want to generate HTML documents which contain hyperlinks to " -#| "different sections of the document using _anchors_. We can accomplish " -#| "this already, by generating anchor names by hand and including them at " -#| "least twice in the document: once at the definition of the anchor itself, " -#| "and once in each hyperlink. However, this approach has some basic issues:" msgid "" "Suppose we want to generate HTML documents that contain hyperlinks to " "different sections of the document using _anchors_. We can accomplish this " @@ -14790,11 +14778,9 @@ msgid "" "document: once at the anchor's definition and once in each hyperlink. " "However, this approach has some basic issues:" msgstr "" -"*アンカー*を使用して文書のさまざまな節へのハイパーリンクが含まれているHTML文" -"書を生成するとします。\n" +"*アンカー*を使用して文書の様々な節へのハイパーリンクが含まれているHTML文書を生成するとします。\n" "これは既に達成できています。\n" -"手作業でアンカーの名前を生成して文書中で少なくとも2回それらを含めればよいので" -"す。\n" +"手作業でアンカーの名前を生成して文書中で少なくとも2回それらを含めればよいのです。\n" "1つはアンカーの定義自身に、もう1つはそれぞれのハイパーリンクにあります。\n" "しかし、この方法には根本的な問題が幾つかあります。" @@ -15872,28 +15858,21 @@ msgstr "`Control.Plus`モジュールには`empty`値が定義されています #. type: Bullet: '- ' #: text/chapter3.md:24 -#, fuzzy -#| msgid "" -#| "The `Data.List` module, which is provided by the `lists` package which " -#| "can be installed using Spago. It contains a few functions which we will " -#| "need for working with linked lists." msgid "" "The `Data.List` module, provided by the `lists` package, which can be " "installed using Spago. It contains a few functions that we will need for " "working with linked lists." msgstr "" -"`Data.List`モジュールは`lists`パッケージで提供されておりSpagoを使ってインス" -"トールできます。\n" -"連結リストを使うために必要な幾つかの関数が含まれています。" +"`Data.List`モジュールは`lists`パッケージで提供されています。\n" +"またこのパッケージはSpagoを使ってインストールできます。\n" +"モジュールには連結リストを使うために必要な幾つかの関数が含まれています。" #. type: Bullet: '- ' #: text/chapter3.md:24 msgid "" "The `Data.Maybe` module, which defines data types and functions for working " "with optional values." -msgstr "" -"`Data.Maybe`モジュールは、オプショナルな値を扱うためのデータ型と関数を定義し" -"ています。" +msgstr "`Data.Maybe`モジュールは、省略可能な値を扱うためのデータ型と関数を定義しています。" #. type: Plain text #: text/chapter3.md:26 @@ -15933,14 +15912,6 @@ msgstr "単純な型" #. type: Plain text #: text/chapter3.md:37 -#, fuzzy -#| msgid "" -#| "PureScript defines three built-in types which correspond to JavaScript's " -#| "primitive types: numbers, strings and booleans. These are defined in the " -#| "`Prim` module, which is implicitly imported by every module. They are " -#| "called `Number`, `String`, and `Boolean`, respectively, and you can see " -#| "them in PSCi by using the `:type` command to print the types of some " -#| "simple values:" msgid "" "PureScript defines three built-in types corresponding to JavaScript's " "primitive types: numbers, strings, and booleans. These are defined in the " @@ -15948,12 +15919,9 @@ msgid "" "`Number`, `String`, and `Boolean`, respectively, and you can see them in " "PSCi by using the `:type` command to print the types of some simple values:" msgstr "" -"JavaScriptのプリミティブ型に対応する組み込みデータ型として、PureScriptでは数" -"値型と文字列型、真偽型の3つが定義されています。\n" -"これらは`Prim`モジュールで定義されており、全てのモジュールに暗黙にインポート" -"されます。\n" -"これらはそれぞれ `Number`、 `String`、 `Boolean`と呼ばれており、PSCiで`:type`" -"コマンドを使うと簡単な値の型を表示させて確認できます。" +"JavaScriptの原始型に対応する組み込みデータ型として、PureScriptでは数値型と文字列型、真偽型の3つが定義されています。\n" +"これらは`Prim`モジュールで定義されており、全てのモジュールに暗黙にインポートされます。\n" +"それぞれ`Number`、`String`、`Boolean`と呼ばれており、PSCiで簡単な値の型を表示するのに`:type`コマンドを使うと確認できます。" #. type: Fenced code block (text) #: text/chapter3.md:38 @@ -15983,10 +15951,6 @@ msgstr "" #. type: Plain text #: text/chapter3.md:52 -#, fuzzy -#| msgid "" -#| "PureScript defines some other built-in types: integers, characters, " -#| "arrays, records, and functions." msgid "" "PureScript defines other built-in types: integers, characters, arrays, " "records, and functions." @@ -16063,18 +16027,12 @@ msgstr "" #. type: Plain text #: text/chapter3.md:81 -#, fuzzy -#| msgid "" -#| "The error in the last example is an error from the type checker, which " -#| "unsuccessfully attempted to _unify_ (i.e. make equal) the types of the " -#| "two elements." msgid "" "The last example shows an error from the type checker, which failed to " "_unify_ (i.e., make equal) the types of the two elements." msgstr "" -"最後の例で起きているエラーは型検証器によって報告されたもので、配列の2つの要素" -"の型を*単一化*(Unification、等価にする意)しようとして失敗したことを示してい" -"ます。" +"最後の例は型検証器によるエラーを示しています。\n" +"配列の2つの要素の型を*単一化*(つまり等価にする意)するのに失敗したのです。" #. type: Plain text #: text/chapter3.md:83 @@ -16105,19 +16063,13 @@ msgstr "" #. type: Plain text #: text/chapter3.md:94 -#, fuzzy -#| msgid "" -#| "This type indicates that the specified object has two _fields_, a `name` " -#| "field which has type `String`, and an `interests` field, which has type " -#| "`Array String`, i.e. an array of `String`s." msgid "" "This type indicates that the specified object has two _fields_: a `name` " "field with the type `String` and an `interests` field with the type `Array " "String`, i.e., an array of `String`s." msgstr "" -"この型が示しているのは、指定されたオブジェクトは、 `String`型のフィールド " -"`name` と `Array String`つまり `String`の配列の型のフィールド `interests` と" -"いう2つの _フィールド_ (field) を持っているということです。" +"この型が示しているのは指定されたオブジェクトが2つの*フィールド*を持っているということです。\n" +"それぞれ`String`型のフィールド`name`と`Array String`型のフィールド`interests`で、後者は`String`の配列ということです。" #. type: Plain text #: text/chapter3.md:96 @@ -16194,24 +16146,15 @@ msgstr "" #. type: Plain text #: text/chapter3.md:124 -#, fuzzy -#| msgid "" -#| "Alternatively, functions can be defined inline, by using a backslash " -#| "character followed by a space-delimited list of argument names. To enter " -#| "a multi-line declaration in PSCi, we can enter \"paste mode\" by using " -#| "the `:paste` command. In this mode, declarations are terminated using the " -#| "_Control-D_ key sequence:" msgid "" "Alternatively, functions can be defined inline using a backslash character " "followed by a space-delimited list of argument names. To enter a multi-line " "declaration in PSCi, we can enter \"paste mode\" using the `:paste` command. " "In this mode, declarations are terminated using the _Control-D_ key sequence:" msgstr "" -"バックスラッシュに続けて空白文字で区切られた引数名のリストを書くことで、関数" -"をインラインでも定義できます。\n" -"PSCiで複数行の宣言を入力するには、 `:paste`コマンドを使用して「貼り付けモー" -"ド」に入ります。\n" -"このモードでは、*Control-D*キーシーケンスを使用して宣言を終了します。" +"代えて、バックスラッシュ文字に続けて空白文字で区切られた引数名のリストを書くことで、関数をインラインでも定義できます。\n" +"PSCiで複数行の宣言を入力するには、`:paste`コマンドを使用して「貼り付けモード」に入ります。\n" +"このモードでは、*Control-D*キーシーケンスを使って宣言を終了します。" #. type: Fenced code block (text) #: text/chapter3.md:125 @@ -16273,34 +16216,23 @@ msgstr "" #. type: Plain text #: text/chapter3.md:149 -#, fuzzy -#| msgid "" -#| "The keyword `forall` here indicates that `flip` has a _universally " -#| "quantified type_. It means that we can substitute any types for `a`, `b` " -#| "and `c`, and `flip` will work with those types." msgid "" "The keyword `forall` here indicates that `flip` has a _universally " "quantified type_. It means we can substitute any types for `a`, `b`, and " "`c`, and `flip` will work with those types." msgstr "" -"この `forall`キーワードは、 `flip`が _全称量化された型_ (universally " -"quantified type) を持っていることを示しています。これは、 `a`や `b`、 `c`をど" -"の型に置き換えても、 `flip`はその型でうまく動作するという意味です。" +"この`forall`キーワードは、`flip`が*全称量化された型*を持つことを示しています。\n" +"つまり`a`や`b`や`c`をどの型に置き換えても良く、`flip`はその型で動作するのです。" #. type: Plain text #: text/chapter3.md:151 -#, fuzzy -#| msgid "" -#| "For example, we might choose the type `a` to be `Int`, `b` to be `String` " -#| "and `c` to be `String`. In that case we could _specialize_ the type of " -#| "`flip` to" msgid "" "For example, we might choose the type `a` to be `Int`, `b` to be `String`, " "and `c` to be `String`. In that case, we could _specialize_ the type of " "`flip` to" msgstr "" -"例えば、 `a`を `Int`、 `b`を `String`、 `c`を `String`というように選んでみた" -"とします。この場合、 `flip`の型を次のように*特殊化* (specialize) できます。" +"例えば、`a`を`Int`、`b`を`String`、`c`を`String`と選んだとします。\n" +"その場合、`flip`の型を次のように*特殊化*できます。" #. type: Fenced code block (text) #: text/chapter3.md:152 @@ -16310,11 +16242,6 @@ msgstr "(Int -> String -> String) -> String -> Int -> String\n" #. type: Plain text #: text/chapter3.md:157 -#, fuzzy -#| msgid "" -#| "We don't have to indicate in code that we want to specialize a quantified " -#| "type - it happens automatically. For example, we can just use `flip` as " -#| "if it had this type already:" msgid "" "We don't have to indicate in code that we want to specialize a quantified " "type – it happens automatically. For example, we can use `flip` as if it had " @@ -16322,8 +16249,7 @@ msgid "" msgstr "" "量化された型を特殊化したいということをコードで示す必要はありません。\n" "特殊化は自動的に行われます。\n" -"例えば次のように単に`flip`を使用できます。\n" -"あたかも既にその型の`flip`を持っていたかのようです。" +"例えば、あたかも既にその型の`flip`を持っていたかのように、`flip`を使えます。" #. type: Fenced code block (text) #: text/chapter3.md:158 @@ -16339,13 +16265,6 @@ msgstr "" #. type: Plain text #: text/chapter3.md:165 -#, fuzzy -#| msgid "" -#| "While we can choose any types for `a`, `b` and `c`, we have to be " -#| "consistent. The type of the function we passed to `flip` had to be " -#| "consistent with the types of the other arguments. That is why we passed " -#| "the string `\"Ten\"` as the second argument, and the number `10` as the " -#| "third. It would not work if the arguments were reversed:" msgid "" "While we can choose any types for `a`, `b`, and `c`, we have to be " "consistent. The type of function passed to `flip` had to be consistent with " @@ -16353,11 +16272,9 @@ msgid "" "as the second argument and the number `10` as the third. It would not work " "if the arguments were reversed:" msgstr "" -"`a`、 `b`、 `c`の型はどんな型でも選ぶことができるといっても、型の不整合は生じ" -"ないようにしなければなりません。\n" -"`flip`に渡す関数の型は、他の引数の型と整合性がなくてはなりません。\n" -"第2引数として文字列 `\"Ten\"`、第3引数として数 `10`を渡したのはそれが理由で" -"す。\n" +"`a`、`b`、`c`の型はどんな型でも選べるといっても、一貫していなければなりません。\n" +"`flip`に渡す関数の型は他の引数の型と整合性がなくてはなりません。\n" +"第2引数として文字列`\"Ten\"`、第3引数として数`10`を渡したのはそれが理由です。\n" "もし引数が逆になっているとうまくいかないでしょう。" #. type: Fenced code block (text) @@ -16402,8 +16319,6 @@ msgstr "" #. type: Plain text #: text/chapter3.md:179 -#, fuzzy -#| msgid "Therefore, the following is valid PureScript code:" msgid "Therefore, the following is a valid PureScript code:" msgstr "したがって、次は正しいPureScriptコードです。" @@ -16419,8 +16334,6 @@ msgstr "" #. type: Plain text #: text/chapter3.md:186 -#, fuzzy -#| msgid "But this is not valid code:" msgid "But this is not a valid code:" msgstr "しかし、次は正しいコードではありません。" @@ -16471,8 +16384,6 @@ msgstr "" #. type: Plain text #: text/chapter3.md:204 -#, fuzzy -#| msgid "but this is not:" msgid "But this is not:" msgstr "しかし、これは正しくありません。" @@ -16557,13 +16468,6 @@ msgstr "{{#include ../exercises/chapter3/src/Data/AddressBook.purs:Entry}}\n" #. type: Plain text #: text/chapter3.md:234 -#, fuzzy -#| msgid "" -#| "This defines a _type synonym_ called `Entry` - the type `Entry` is " -#| "equivalent to the type on the right of the equals symbol: a record type " -#| "with three fields - `firstName`, `lastName` and `address`. The two name " -#| "fields will have type `String`, and the `address` field will have type " -#| "`Address`, defined as follows:" msgid "" "This defines a _type synonym_ called `Entry` – the type `Entry` is " "equivalent to the type on the right of the equals symbol: a record type with " @@ -16571,13 +16475,10 @@ msgid "" "will have the type `String`, and the `address` field will have the type " "`Address`, defined as follows:" msgstr "" -"これは `Entry`という*型同義語*(type synonym、型シノニム)を定義していま" -"す。\n" -"型 `Entry`は等号の右辺と同じ型ということです。\n" -"レコードの型は何れも文字列である `firstName`、 `lastName`、 `phone`という3つ" -"のフィールドからなります。\n" -"前者の2つのフィールドは型 `String`を持ち、 `address`は以下のように定義された" -"型 `Address`を持っています。" +"これは`Entry`という*型同義語*を定義しています。\n" +"型`Entry`は等号の右辺と等価ということです。\n" +"レコードの型は`firstName`、`lastName`、`phone`という3つのフィールドからなります。\n" +"2つの名前のフィールドは型`String`を持ち、`address`は以下で定義された型`Address`を持ちます。" #. type: Fenced code block (haskell) #: text/chapter3.md:235 @@ -16592,16 +16493,12 @@ msgstr "なお、レコードには他のレコードを含めることができ #. type: Plain text #: text/chapter3.md:242 -#, fuzzy -#| msgid "" -#| "Now let's define a third type synonym, for our address book data " -#| "structure, which will be represented simply as a linked list of entries:" msgid "" "Now let's define a third type synonym for our address book data structure, " "which will be represented simply as a linked list of entries:" msgstr "" -"それでは、3つめの型同義語も定義してみましょう。住所録のデータ構造としては、単" -"に項目の連結リストとして格納することにします。" +"それでは、住所録のデータ構造として3つめの型同義語も定義してみましょう。\n" +"単に項目の連結リストとして表すことにします。" #. type: Fenced code block (haskell) #: text/chapter3.md:243 @@ -16611,16 +16508,12 @@ msgstr "{{#include ../exercises/chapter3/src/Data/AddressBook.purs:AddressBook}} #. type: Plain text #: text/chapter3.md:248 -#, fuzzy -#| msgid "" -#| "Note that `List Entry` is not the same as `Array Entry`, which represents " -#| "an _array_ of entries." msgid "" "Note that `List Entry` differs from `Array Entry`, which represents an " "_array_ of entries." msgstr "" -"`List Entry`は `Array Entry`とは同じではないということに注意してください。 " -"`Array Entry`は住所録の項目の _配列_ を意味しています。" +"なお、`List Entry`は `Array Entry`とは同じではありません。\n" +"後者は項目の*配列*を表しています。" #. type: Title ## #: text/chapter3.md:249 @@ -16642,21 +16535,14 @@ msgstr "" #. type: Plain text #: text/chapter3.md:254 -#, fuzzy -#| msgid "" -#| "Note that just like function application, type constructors are applied " -#| "to other types simply by juxtaposition: the type `List Entry` is in fact " -#| "the type constructor `List` _applied_ to the type `Entry` - it represents " -#| "a list of entries." msgid "" "Note that just like function application, type constructors are applied to " "other types simply by juxtaposition: the type `List Entry` is, in fact, the " "type constructor `List` _applied_ to the type `Entry` – it represents a list " "of entries." msgstr "" -"ちょうど関数適用と同じように、型構築子は他の型に並べることで適用されることに" -"注意してください。型 `List Entry`は実は型構築子 `List`が型 `Entry`に _適用_ " -"されたものです。これは住所録項目のリストを表しています。" +"なお、ちょうど関数適用と同じように、型構築子は他の型に並置するだけで適用されます。\n" +"実際、型`List Entry`は型構築子`List`が型`Entry`に*適用*されたもので、項目のリストを表しています。" #. type: Plain text #: text/chapter3.md:256 @@ -16781,19 +16667,13 @@ msgstr "{{#include ../exercises/chapter3/src/Data/AddressBook.purs:showEntry_sig #. type: Plain text #: text/chapter3.md:294 -#, fuzzy -#| msgid "" -#| "This type signature says that `showEntry` is a function, which takes an " -#| "`Entry` as an argument and returns a `String`. Here is the code for " -#| "`showEntry`:" msgid "" "This type signature says that `showEntry` is a function that takes an " "`Entry` as an argument and returns a `String`. Here is the code for " "`showEntry`:" msgstr "" -"`showEntry`は引数として `Entry`を取り `String`を返す関数であるということを、" -"この型シグネチャは言っています。\n" -"`showEntry`のコードは次の通りです。" +"この型シグネチャが言っているのは、`showEntry`は引数として`Entry`を取り`String`を返す関数であるということです。\n" +"以下は`showEntry`のコードです。" #. type: Fenced code block (haskell) #: text/chapter3.md:295 @@ -16928,16 +16808,12 @@ msgstr "住所録の作成" #. type: Plain text #: text/chapter3.md:351 -#, fuzzy -#| msgid "" -#| "Now let's write some utility functions for working with address books. We " -#| "will need a value which represents an empty address book: an empty list." msgid "" "Now let's write some utility functions for working with address books. We " "will need a value representing an empty address book: an empty list." msgstr "" -"今度は住所録の操作を支援する関数を幾つか書いてみましょう。\n" -"空の住所録を表す値が必要ですが、これには空のリストを使います。" +"今度は住所録を扱う補助関数を幾つか書いてみましょう。\n" +"空の住所録を表す値が必要ですが、これは空のリストです。" #. type: Fenced code block (haskell) #: text/chapter3.md:352 @@ -16962,29 +16838,14 @@ msgstr "{{#include ../exercises/chapter3/src/Data/AddressBook.purs:insertEntry_s #. type: Plain text #: text/chapter3.md:363 -#, fuzzy -#| msgid "" -#| "This type signature says that `insertEntry` takes an `Entry` as its first " -#| "argument, and an `AddressBook` as a second argument, and returns a new " -#| "`AddressBook`." msgid "" "This type signature says that `insertEntry` takes an `Entry` as its first " "argument, an `AddressBook` as a second argument, and returns a new " "`AddressBook`." -msgstr "" -"この型シグネチャに書かれているのは、最初の引数として `Entry`、第二引数として " -"`AddressBook`を取り、新しい `AddressBook`を返すということです。" +msgstr "この型シグネチャに書かれているのは、最初の引数として`Entry`、第2引数として`AddressBook`を取り、新しい`AddressBook`を返すということです。" #. type: Plain text #: text/chapter3.md:365 -#, fuzzy -#| msgid "" -#| "We don't modify the existing `AddressBook` directly. Instead, we return a " -#| "new `AddressBook` which contains the same data. As such, `AddressBook` is " -#| "an example of an _immutable data structure_. This is an important idea in " -#| "PureScript - mutation is a side-effect of code, and inhibits our ability " -#| "to reason effectively about its behavior, so we prefer pure functions and " -#| "immutable data where possible." msgid "" "We don't modify the existing `AddressBook` directly. Instead, we return a " "new `AddressBook`, which contains the same data. As such, `AddressBook` is " @@ -16993,14 +16854,12 @@ msgid "" "reason effectively about its behavior, so we prefer pure functions and " "immutable data where possible." msgstr "" -"既存の `AddressBook`を直接変更することはしません。\n" -"その代わりに、同じデータが含まれている新しい `AddressBook`を返すようにしま" -"す。\n" -"このように、 `AddressBook`は*不変データ構造*の一例となっています。\n" +"既存の`AddressBook`を直接変更することはしません。\n" +"代わりに、同じデータが含まれている新しい`AddressBook`を返します。\n" +"このように`AddressBook`は*不変データ構造*の一例となっています。\n" "これはPureScriptにおける重要な考え方です。\n" -"変更はコードの副作用であり、効率の良いコードの挙動を考えるときの妨げになりま" -"す。\n" -"そのため、可能な限り純粋な関数や不変のデータにする方が好ましいのです。" +"変更はコードの副作用であり、効率良く挙動を探る上で妨げになります。\n" +"そのため可能な限り純粋関数や不変なデータにする方が好ましいのです。" #. type: Plain text #: text/chapter3.md:367 @@ -17031,19 +16890,12 @@ msgstr "" #. type: Plain text #: text/chapter3.md:378 -#, fuzzy -#| msgid "" -#| "This type signature says that `Cons` takes a value of some type `a`, and " -#| "a list of elements of type `a`, and returns a new list with entries of " -#| "the same type. Let's specialize this with `a` as our `Entry` type:" msgid "" "This type signature says that `Cons` takes a value of some type `a`, takes a " "list of elements of type `a`, and returns a new list with entries of the " "same type. Let's specialize this with `a` as our `Entry` type:" msgstr "" -"この型シグネチャで書かれているのは、`Cons`が何らかの型`a`の値と型`a`を要素に" -"持つリストを引数に取り、同じ型の要素を持つ新しいリストを返すということで" -"す。\n" +"この型シグネチャで書かれているのは、`Cons`が何らかの型`a`の値と型`a`の要素のリストを取り、同じ型の項目を持つ新しいリストを返すということです。\n" "`a`を`Entry`型として特殊化してみましょう。" #. type: Fenced code block (haskell) @@ -17089,18 +16941,13 @@ msgstr "insertEntry entry book = Cons entry book\n" #. type: Plain text #: text/chapter3.md:398 -#, fuzzy -#| msgid "" -#| "This brings the two arguments `entry` and `book` into scope, on the left " -#| "hand side of the equals symbol, and then applies the `Cons` function to " -#| "create the result." msgid "" "This brings the two arguments `entry` and `book` into scope – on the left-" "hand side of the equals symbol – and then applies the `Cons` function to " "create the result." msgstr "" -"等号の左側にある2つの引数`entry`と`book`がスコープに導入されますから、これら" -"に `Cons`関数を適用して結果の値を作成しています。" +"こうすると、等号の左側にある2つの引数`entry`と`book`がスコープに導入されます。\n" +"それから`Cons`関数を適用し、結果を作成しています。" #. type: Title ## #: text/chapter3.md:399 @@ -17110,19 +16957,13 @@ msgstr "カリー化された関数" #. type: Plain text #: text/chapter3.md:402 -#, fuzzy -#| msgid "" -#| "Functions in PureScript take exactly one argument. While it looks like " -#| "the `insertEntry` function takes two arguments, it is in fact an example " -#| "of a _curried function_." msgid "" "Functions in PureScript take exactly one argument. While it looks like the " "`insertEntry` function takes two arguments, it is an example of a _curried " "function_." msgstr "" -"PureScriptでは、関数は常に1つの引数だけを取ります。`insertEntry`関数は2つの引" -"数を取るように見えますが、これは実際には*カリー化された関数*の一例となってい" -"ます。" +"PureScriptでは、関数は常に1つの引数だけを取ります。\n" +"`insertEntry`関数は2つの引数を取るように見えますが、*カリー化された関数*の一例なのです。" #. type: Plain text #: text/chapter3.md:404 @@ -17138,32 +16979,23 @@ msgstr "Entry -> (AddressBook -> AddressBook)\n" #. type: Plain text #: text/chapter3.md:410 -#, fuzzy -#| msgid "" -#| "That is, `insertEntry` is a function which returns a function! It takes a " -#| "single argument, an `Entry`, and returns a new function, which in turn " -#| "takes a single `AddressBook` argument and returns a new `AddressBook`." msgid "" "That is, `insertEntry` is a function that returns a function! It takes a " "single argument, an `Entry`, and returns a new function, which in turn takes " "a single `AddressBook` argument and returns a new `AddressBook`." msgstr "" -"すなわち、 `insertEntry`は関数を返す関数である、ということです。\n" -"この関数は単一の引数 `Entry`を取り、それから単一の引数 `AddressBook`を取り新" -"しい `AddressBook`を返す新しい関数を返すのです。" +"すなわち、`insertEntry`は関数を返す関数なのです。\n" +"この関数は単一の引数`Entry`を取り、新しい関数を返します。\n" +"今度はこの関数が単一の引数`AddressBook`を取り、新しい`AddressBook`を返します。" #. type: Plain text #: text/chapter3.md:412 -#, fuzzy -#| msgid "" -#| "This means that we can _partially apply_ `insertEntry` by specifying only " -#| "its first argument, for example. In PSCi, we can see the result type:" msgid "" "This means we can _partially apply_ `insertEntry` by specifying only its " "first argument, for example. In PSCi, we can see the result type:" msgstr "" -"これは例えば、最初の引数だけを与えると `insertEntry`を _部分適用_ (partial " -"application) できることを意味します。PSCiでこの結果の型を見てみましょう。" +"これはつまり、最初の引数だけを与えて`insertEntry`を*部分適用*できたりするということです。\n" +"PSCiで結果の型が見られます。" #. type: Fenced code block (text) #: text/chapter3.md:413 @@ -17198,14 +17030,12 @@ msgstr "" #. type: Plain text #: text/chapter3.md:427 -#, fuzzy -#| msgid "" -#| "Note though that the parentheses here are unnecessary - the following is " -#| "equivalent:" msgid "" "Note though, that the parentheses here are unnecessary – the following is " "equivalent:" -msgstr "ここで括弧は不要であることにも注意してください。次の式は同等です。" +msgstr "" +"ただし、ここでの括弧は不要です。\n" +"以下は等価です。" #. type: Fenced code block (text) #: text/chapter3.md:428 @@ -17219,23 +17049,15 @@ msgstr "" #. type: Plain text #: text/chapter3.md:434 -#, fuzzy -#| msgid "" -#| "This is because function application associates to the left, and this " -#| "explains why we can just specify function arguments one after the other, " -#| "separated by whitespace." msgid "" "This is because function application associates to the left, which explains " "why we can specify function arguments one after the other, separated by " "whitespace." -msgstr "" -"これは関数適用が左結合であるためで、なぜ空白で区切った引数を関数に指定するだ" -"けでいいのかの説明にもなっています。" +msgstr "これは関数適用が左に結合するためで、なぜ空白で区切った引数を次々に関数に指定するだけでいいのかの説明にもなっています。" #. type: Plain text #: text/chapter3.md:436 -#, fuzzy, no-wrap -#| msgid "The `->` operator in function types is a _type constructor_ for functions. It takes two type arguments, the function's argument type and the return type. The left and right operands respectively.\n" +#, no-wrap msgid "The `->` operator in function types is a _type constructor_ for functions. It takes two type arguments: the function's argument type and the return type – the left and right operands, respectively.\n" msgstr "" "関数の型の`->`演算子は関数の*型構築子*です。\n" @@ -17272,13 +17094,6 @@ msgstr "" #. type: Plain text #: text/chapter3.md:447 -#, fuzzy -#| msgid "" -#| "If we explicitly parenthesize the right-hand side, we get `(Cons entry) " -#| "book`. That is, `insertEntry entry` is a function whose argument is just " -#| "passed along to the `(Cons entry)` function. But if two functions have " -#| "the same result for every input, then they are the same function! So we " -#| "can remove the argument `book` from both sides:" msgid "" "If we explicitly parenthesize the right-hand side, we get `(Cons entry) " "book`. That is, `insertEntry entry` is a function whose argument is just " @@ -17286,12 +17101,10 @@ msgid "" "same result for every input, then they are the same! So we can remove the " "argument `book` from both sides:" msgstr "" -"もし式の右辺に明示的に括弧をつけるなら、 `(Cons entry) book`となります。\n" -"`insertEntry entry`はその引数が単に関数 `(Cons entry)`に渡されるような関数だ" -"ということです。\n" -"でもこの2つの関数はどんな入力についても同じ結果を返しますから、つまりこれらは" -"同じ関数です。\n" -"よって、両辺から引数 `book`を削除できます。" +"もし式の右辺に明示的に括弧をつけるなら、`(Cons entry) book`となります。\n" +"つまり`insertEntry entry`はその引数が単に関数`(Cons entry)`に渡されるような関数だということです。\n" +"ところがこの2つの関数はどんな入力についても同じ結果を返すので、となると同じ関数ではないですか。\n" +"よって、両辺から引数`book`を削除できます。" #. type: Fenced code block (haskell) #: text/chapter3.md:448 @@ -17316,36 +17129,23 @@ msgstr "{{#include ../exercises/chapter3/src/Data/AddressBook.purs:insertEntry}} #. type: Plain text #: text/chapter3.md:460 -#, fuzzy -#| msgid "" -#| "This process is called _eta conversion_, and can be used (along with some " -#| "other techniques) to rewrite functions in _point-free form_, which means " -#| "functions defined without reference to their arguments." msgid "" "This process, called _eta conversion_, can be used (along with other " "techniques) to rewrite functions in _point-free form_, which means functions " "defined without reference to their arguments." msgstr "" -"この処理は _イータ変換_ (eta conversion) と呼ばれ、(その他の技法を併用して)" -"引数を参照することなく関数を定義する _ポイントフリー形式_ (point-free form) " -"へと関数を書き換えるのに使うことができます。" +"この処理は*イータ変換*と呼ばれ、(その他の技法を併用して)*ポイントフリー形式*へと関数を書き換えるのに使えます。\n" +"つまり、引数を参照せずに関数を定義できるのです。" #. type: Plain text #: text/chapter3.md:462 -#, fuzzy -#| msgid "" -#| "In the case of `insertEntry`, _eta conversion_ has resulted in a very " -#| "clear definition of our function - \"`insertEntry` is just cons on " -#| "lists\". However, it is arguable whether point-free form is better in " -#| "general." msgid "" "In the case of `insertEntry`, _eta conversion_ has resulted in a very clear " "definition of our function – \"`insertEntry` is just cons on lists\". " "However, it is arguable whether the point-free form is better in general." msgstr "" -"`insertEntry`の場合には、イータ変換によって「`insertEntry`は単にリストに対す" -"るconsだ」となり、関数の定義はとても明確になりました。しかし、一般的にポイン" -"トフリー形式のほうがいいのかどうかには議論の余地があります。" +"`insertEntry`の場合、イータ変換によって「`insertEntry`は単にリストにおけるconsだ」となり、とても明快な関数の定義になりました。\n" +"しかし、一般にポイントフリー形式のほうがいいのかどうかには議論の余地があります。" #. type: Title ## #: text/chapter3.md:463 @@ -17437,52 +17237,34 @@ msgstr "住所録に問い合わせる" #. type: Plain text #: text/chapter3.md:498 -#, fuzzy -#| msgid "" -#| "The last function we need to implement for our minimal address book " -#| "application will look up a person by name and return the correct `Entry`. " -#| "This will be a nice application of building programs by composing small " -#| "functions - a key idea from functional programming." msgid "" "The last function we need to implement for our minimal address book " "application will look up a person by name and return the correct `Entry`. " "This will be a nice application of building programs by composing small " "functions – a key idea from functional programming." msgstr "" -"最小限の住所録アプリケーションの実装で必要になる最後の関数は、名前で人を検索" -"し適切な `Entry`を返すものです。これは小さな関数を組み合わせることでプログラ" -"ムを構築するという、関数型プログラミングで鍵となる考え方のよい応用例になるで" -"しょう。" +"最小限の住所録アプリケーションの実装で必要になる最後の関数は、名前で人を検索し適切な`Entry`を返すものです。\n" +"これは小さな関数を組み合わせることでプログラムを構築するという、関数型プログラミングで鍵となる考え方のよい応用例になるでしょう。" #. type: Plain text #: text/chapter3.md:500 -#, fuzzy -#| msgid "" -#| "We can first filter the address book, keeping only those entries with the " -#| "correct first and last names. Then we can simply return the head (i.e. " -#| "first) element of the resulting list." msgid "" "We can filter the address book, keeping only those entries with the correct " "first and last names. Then we can return the head (i.e., first) element of " "the resulting list." msgstr "" -"まずは住所録を絞り込み、該当する姓名を持つ項目だけを保持するようにするのがい" -"いでしょう。それから、結果のリストの先頭の (head) 要素を返すだけです。" +"住所録を絞り込めば該当する姓名を持つ項目だけを保持するようにできます。\n" +"そうすれば結果のリストの先頭(つまり最初)の要素を返せます。" #. type: Plain text #: text/chapter3.md:502 -#, fuzzy -#| msgid "" -#| "With this high-level specification of our approach, we can calculate the " -#| "type of our function. First open PSCi, and find the types of the `filter` " -#| "and `head` functions:" msgid "" "With this high-level specification of our approach, we can calculate the " "type of our function. First, open PSCi, and find the types of the `filter` " "and `head` functions:" msgstr "" -"この大まかな仕様に従って、この関数の型を計算できます。まずPSCiを起動し、 " -"`filter`関数と `head`関数の型を見てみましょう。" +"この大まかな道筋の仕様があれば関数の型を計算できます。\n" +"まずPSCiを開いて`filter`関数と`head`関数の型を探してみましょう。" #. type: Fenced code block (text) #: text/chapter3.md:503 @@ -17518,31 +17300,18 @@ msgstr "" #. type: Plain text #: text/chapter3.md:519 -#, fuzzy -#| msgid "" -#| "`filter` is a curried function of two arguments. Its first argument is a " -#| "function, which takes an element of the list and returns a `Boolean` " -#| "value as a result. Its second argument is a list of elements, and the " -#| "return value is another list." msgid "" "`filter` is a curried function of two arguments. Its first argument is a " "function, which takes an element of the list and returns a `Boolean` value. " "Its second argument is a list of elements, and the return value is another " "list." msgstr "" -"`filter`はカリー化された2引数の関数です。\n" -"最初の引数は、リストの要素を取り `Boolean`値を結果として返す関数です。\n" +"`filter`は2引数のカリー化された関数です。\n" +"最初の引数は関数で、リストの要素を取り`Boolean`値を返します。\n" "第2引数は要素のリストで、返り値は別のリストです。" #. type: Plain text #: text/chapter3.md:521 -#, fuzzy -#| msgid "" -#| "`head` takes a list as its argument, and returns a type we haven't seen " -#| "before: `Maybe a`. `Maybe a` represents an optional value of type `a`, " -#| "and provides a type-safe alternative to using `null` to indicate a " -#| "missing value in languages like JavaScript. We will see it again in more " -#| "detail in later chapters." msgid "" "`head` takes a list as its argument and returns a type we haven't seen " "before: `Maybe a`. `Maybe a` represents an optional value of type `a`, and " @@ -17550,12 +17319,9 @@ msgid "" "in languages like JavaScript. We will see it again in more detail in later " "chapters." msgstr "" -"`head`は引数としてリストを取り、 `Maybe a`という今まで見たことがないような型" -"を返します。\n" -"`Maybe a`は型 `a`のオプショナルな値、つまり `a`の値を持つか持たないかのどちら" -"かの値を示しており、JavaScriptのような言語で値がないことを示すために使われる " -"`null`の型安全な代替手段を提供します。\n" -"これについては後の章で詳しく扱います。" +"`head`は引数としてリストを取り、 `Maybe a`という今までに見たことがない型を返します。\n" +"`Maybe a`は型`a`の省略可能な値を表しており、JavaScriptのような言語で値がないことを示すための`null`を使う代わりとなる、型安全な代替を提供します。\n" +"後の章で改めて詳しく見ていきます。" #. type: Plain text #: text/chapter3.md:523 @@ -17580,14 +17346,10 @@ msgstr "" #. type: Plain text #: text/chapter3.md:531 -#, fuzzy -#| msgid "" -#| "We know that we will need to pass the first and last names that we want " -#| "to search for, as arguments to our function." msgid "" "We know that we will need to pass the first and last names that we want to " "search for as arguments to our function." -msgstr "検索する関数の引数として姓と名前を渡す必要があるのもわかっています。" +msgstr "関数の引数として姓名を渡す必要があるだろうということは分かっています。" #. type: Plain text #: text/chapter3.md:533 @@ -17612,22 +17374,14 @@ msgstr "{{#include ../exercises/chapter3/src/Data/AddressBook.purs:findEntry_sig #. type: Plain text #: text/chapter3.md:541 -#, fuzzy -#| msgid "" -#| "This type signature says that `findEntry` takes two strings, the first " -#| "and last names, and a `AddressBook`, and returns an optional `Entry`. The " -#| "optional result will contain a value only if the name is found in the " -#| "address book." msgid "" "This type signature says that `findEntry` takes two strings: the first and " "last names, takes an `AddressBook`, and returns an optional `Entry`. The " "optional result will contain a value only if the name is found in the " "address book." msgstr "" -"この型シグネチャで書かれているのは、`findEntry`が姓と名前の2つの文字列及び" -"`AddressBook`を引数に取り、`Entry`のオプション型の値を結果として返すというこ" -"とです。\n" -"オプショナルな結果は名前が住所録で発見された場合にのみ値を持ちます。" +"この型シグネチャで書かれているのは、`findEntry`が姓と名前の2つの文字列及び`AddressBook`を引数に取り、省略可能な`Entry`を返すということです。\n" +"省略可能な結果は名前が住所録に見付かった場合にのみ値を持ちます。" #. type: Plain text #: text/chapter3.md:543 @@ -17664,18 +17418,13 @@ msgstr "" #. type: Plain text #: text/chapter3.md:556 -#, fuzzy -#| msgid "" -#| "The right hand side of the definition combines the `filter` and `head` " -#| "functions: first, the list of entries is filtered, and the `head` " -#| "function is applied to the result." msgid "" "The right-hand side of the definition combines the `filter` and `head` " "functions: first, the list of entries is filtered, and the `head` function " "is applied to the result." msgstr "" -"定義の右辺では `filter`関数と `head`関数が組み合わされています。\n" -"まず項目のリストを絞り込み、その結果に `head`関数を適用しています。" +"定義の右辺では`filter`関数と`head`関数が組み合わさっています。\n" +"まず項目のリストを絞り込み、その結果に`head`関数を適用しています。" #. type: Plain text #: text/chapter3.md:558 @@ -17697,19 +17446,13 @@ msgstr "" #. type: Plain text #: text/chapter3.md:560 -#, fuzzy -#| msgid "" -#| "Note that, just like for top-level declarations, it was not necessary to " -#| "specify a type signature for `filterEntry`. However, doing so is " -#| "recommended as a form of documentation." msgid "" "Note that, just like for top-level declarations, it was unnecessary to " "specify a type signature for `filterEntry`. However, doing so is recommended " "as a form of documentation." msgstr "" -"最上位での宣言と同じように、必ずしも `filterEntry`の型シグネチャを指定しなく" -"てもよいことに注意してください。ただし、ドキュメントとしても役に立つので型シ" -"グネチャを書くことは推奨されています。" +"なお、最上位での宣言と同じように、必ずしも`filterEntry`の型シグネチャを指定しなくても構いません。\n" +"ただし、ドキュメントの一形態として指定しておくことが推奨されます。" #. type: Title ## #: text/chapter3.md:561 @@ -17719,21 +17462,15 @@ msgstr "中置の関数適用" #. type: Plain text #: text/chapter3.md:564 -#, fuzzy -#| msgid "" -#| "Most of the functions discussed so far used _prefix_ function " -#| "application, where the function name was put _before_ the arguments. For " -#| "example, when using the `insertEntry` function to add an `Entry` (`john`) " -#| "to an empty `AddressBook`, we might write:" msgid "" "Most functions discussed so far used _prefix_ function application, where " "the function name was put _before_ the arguments. For example, when using " "the `insertEntry` function to add an `Entry` (`john`) to an empty " "`AddressBook`, we might write:" msgstr "" -"これまでお話しした関数のほとんどは _前置_ 関数適用でした。関数名が引数の _前" -"_ に置かれていたということです。例えば`insertEntry`関数を使って`Entry` " -"(`john`) を空の`AddressBook`に追加する場合、以下のように書けます。" +"これまでお話しした関数のほとんどは*前置*関数適用でした。\n" +"関数名が引数の*前*に置かれていたということです。\n" +"例えば`insertEntry`関数を使って`Entry` (`john`) を空の`AddressBook`に追加する場合、以下のように書けます。" #. type: Fenced code block (haskell) #: text/chapter3.md:565 @@ -17743,16 +17480,6 @@ msgstr "> book1 = insertEntry john emptyBook\n" #. type: Plain text #: text/chapter3.md:570 -#, fuzzy -#| msgid "" -#| "However, this chapter has also included examples of _infix_ [binary " -#| "operators](https://github.com/purescript/documentation/blob/master/" -#| "language/Syntax.md#binary-operators), such as the `==` operator in the " -#| "definition of `filterEntry`, where the operator is put _between_ the two " -#| "arguments. These infix operators are actually defined in the PureScript " -#| "source as infix aliases for their underlying _prefix_ implementations. " -#| "For example, `==` is defined as an infix alias for the prefix `eq` " -#| "function with the line:" msgid "" "However, this chapter has also included examples of _infix_ [binary " "operators](https://github.com/purescript/documentation/blob/master/language/" @@ -17762,12 +17489,10 @@ msgid "" "their underlying _prefix_ implementations. For example, `==` is defined as " "an infix alias for the prefix `eq` function with the line:" msgstr "" -"しかしこの章には _中置_ [2引数演算子](https://github.com/purescript/" -"documentation/blob/master/language/Syntax.md#binary-operators)の例も含まれて" -"います。例えば`filterEntry`の定義中の`==`演算子で、演算子が2つの引数の _間_ " -"に置かれています。実はこうした中置演算子はPureScriptのソースコードで、背後に" -"ある _前置_ 版の実装への中置別称として定義されています。例えば`==`は以下の行" -"により前置の`eq`関数の中置別称として定義されています。" +"しかし本章には*中置*[2引数演算子](https://github.com/purescript/documentation/blob/master/language/Syntax.md#binary-operators)の例も含まれています。\n" +"例えば`filterEntry`の定義中の`==`演算子で、2つの引数の*間*に置かれています。\n" +"PureScriptのソースコードでこうした中置演算子は隠れた*前置*の実装への中置別称として定義されています。\n" +"例えば`==`は以下の行により前置の`eq`関数の中置別称として定義されています。" #. type: Fenced code block (haskell) #: text/chapter3.md:571 @@ -17777,33 +17502,21 @@ msgstr "infix 4 eq as ==\n" #. type: Plain text #: text/chapter3.md:576 -#, fuzzy -#| msgid "" -#| "and therefore `entry.firstName == firstName` in `filterEntry` could be " -#| "replaced with the `eq entry.firstName firstName`. We'll cover a few more " -#| "examples of defining infix operators later in this section." msgid "" "Therefore `entry.firstName == firstName` in `filterEntry` could be replaced " "with the `eq entry.firstName firstName`. We'll cover a few more examples of " "defining infix operators later in this section." msgstr "" -"したがって`filterEntry`中の`entry.firstName == firstName`は`eq entry." -"firstName firstName`で置き換えられます。この節の後のほうで中置演算子を定義す" -"る例にもう少し触れます。" +"したがって`filterEntry`中の`entry.firstName == firstName`は`eq entry.firstName firstName`で置き換えられます。\n" +"この節の後のほうで中置演算子を定義する例にもう少し触れます。" #. type: Plain text #: text/chapter3.md:578 -#, fuzzy -#| msgid "" -#| "There are situations where putting a prefix function in an infix position " -#| "as an operator leads to more readable code. One example is the `mod` " -#| "function:" msgid "" "In some situations, putting a prefix function in an infix position as an " "operator leads to more readable code. One example is the `mod` function:" msgstr "" -"前置関数を演算子としての中置の位置に置くとより読みやすいコードになる場面があ" -"ります。\n" +"前置関数を演算子としての中置の位置に置くと、より読みやすいコードになる場面があります。\n" "その一例が`mod`関数です。" #. type: Fenced code block (text) @@ -17818,19 +17531,14 @@ msgstr "" #. type: Plain text #: text/chapter3.md:585 -#, fuzzy -#| msgid "" -#| "The above usage works fine, but is awkward to read. A more familiar " -#| "phrasing is \"eight mod three\", which you can achieve by wrapping a " -#| "prefix function in backticks (\\`):" msgid "" "The above usage works fine but is awkward to read. A more familiar phrasing " "is \"eight mod three\", which you can achieve by wrapping a prefix function " "in backticks (\\`):" msgstr "" -"上の用例は正しく動きますが、読みづらいです。\n" -"より馴染みのある表現の仕方は「8 mod 3」ですが、バックスラッシュ (\\`) の中に" -"前置関数を包めばこのように書けます。" +"上の用例でも充分動作しますが、読みにくいです。\n" +"より馴染みのある表現の仕方は「8 mod 3」です。\n" +"バックスラッシュ (\\`) の中に前置関数を包むとそのように書けます。" #. type: Fenced code block (text) #: text/chapter3.md:586 @@ -17917,14 +17625,10 @@ msgstr "book5 = john ++ (peggy ++ (ned ++ emptyBook))\n" #. type: Plain text #: text/chapter3.md:618 -#, fuzzy -#| msgid "" -#| "and the right associativity of our new `++` operator lets us get rid of " -#| "the parentheses without changing the meaning:" msgid "" "The right associativity of our new `++` operator lets us get rid of the " "parentheses without changing the meaning:" -msgstr "そして新しい`++`演算子が右結合なので意味を変えずに括弧を除去できます。" +msgstr "新しい`++`演算子の右結合性により、意味を変えずに括弧を除去できます。" #. type: Fenced code block (haskell) #: text/chapter3.md:619 @@ -17968,19 +17672,13 @@ msgstr "" #. type: Plain text #: text/chapter3.md:634 -#, fuzzy -#| msgid "" -#| "Note that `$` isn't special syntax that's hardcoded into the language. " -#| "It's simply the infix operator for a regular function called `apply`, " -#| "which is defined in `Data.Function` as follows:" msgid "" "Note that `$` isn't a special syntax hardcoded into the language. It's " "simply the infix operator for a regular function called `apply`, which is " "defined in `Data.Function` as follows:" msgstr "" "なお、`($)`は言語にハードコードされた特別な構文ではありません。\n" -"単に`apply`という名前の通常の関数のための中置演算子であって、`Data.Function`" -"で以下のように定義されています。" +"単に`apply`という名前の普通の関数のための中置演算子であって、`Data.Function`で以下のように定義されています。" #. type: Fenced code block (haskell) #: text/chapter3.md:635 @@ -18202,21 +17900,14 @@ msgstr "" #. type: Plain text #: text/chapter3.md:713 -#, fuzzy -#| msgid "" -#| "I will let you make your own decision which definition is easier to " -#| "understand, but it is often useful to think of functions as building " -#| "blocks in this way - each function executing a single task, and solutions " -#| "assembled using function composition." msgid "" "I will let you decide which definition is easier to understand, but it is " "often useful to think of functions as building blocks in this way: each " "function executes a single task, and solutions are assembled using function " "composition." msgstr "" -"どちらの定義のほうがわかりやすいかの判断はお任せしますが、このように関数を部" -"品として捉えると有用なことがよくあります。関数は1つの役目だけをこなし、機能を" -"関数合成で組み立てるというように。" +"どちらの定義のほうが分かりやすいかの判断はお任せしますが、このように関数を部品として捉えるとしばしば有用です。\n" +"各関数は1つの役目をこなすようにし、解法を関数合成を使って組み立てるのです。" #. type: Bullet: ' 1. ' #: text/chapter3.md:721 @@ -18261,33 +17952,17 @@ msgstr "" #. type: Bullet: ' 1. ' #: text/chapter3.md:721 -#, fuzzy -#| msgid "" -#| "(Medium) Write a function `isInBook` which tests whether a name appears " -#| "in a `AddressBook`, returning a Boolean value. _Hint_: Use PSCi to find " -#| "the type of the `Data.List.null` function, which tests whether a list is " -#| "empty or not." msgid "" "(Medium) Write a function `isInBook` that tests whether a name appears in a " "`AddressBook`, returning a Boolean value. _Hint_: Use PSCi to find the type " "of the `Data.List.null` function, which tests whether a list is empty or not." msgstr "" -"(普通)指定された名前が `AddressBook`に存在するかどうかを調べて真偽値で返す" -"関数`isInBook`を書いてみましょう。\n" -"*手掛かり*:リストが空かどうかを調べる `Data.List.null`関数の型をPSCiで調べて" -"みてみましょう。" +"(普通)名前が`AddressBook`に存在するかどうかを調べて真偽値で返す関数`isInBook`を書いてみましょう。\n" +"*手掛かり*:PSCiを使って`Data.List.null`関数の型を見付けてください。\n" +"この関数はリストが空かどうかを調べます。" #. type: Bullet: ' 1. ' #: text/chapter3.md:721 -#, fuzzy -#| msgid "" -#| "(Difficult) Write a function `removeDuplicates` which removes " -#| "\"duplicate\" address book entries. We'll consider entries duplicated if " -#| "they share the same first and last names, while ignoring `address` " -#| "fields. _Hint_: Use PSCi to find the type of the `Data.List.nubByEq` " -#| "function, which removes duplicate elements from a list based on an " -#| "equality predicate. Note that the first element in each set of duplicates " -#| "(closest to list head) is the one that is kept." msgid "" "(Difficult) Write a function `removeDuplicates` which removes \"duplicate\" " "address book entries. We'll consider entries duplicated if they share the " @@ -18297,85 +17972,56 @@ msgid "" "first element in each set of duplicates (closest to the list head) is the " "one that is kept." msgstr "" -"(難しい)「重複」している項目を住所録から削除する関数 `removeDuplicates`を書" -"いてみましょう。\n" -"項目が同じ姓名を共有していれば`address`フィールドに関係なく、項目が重複してい" -"ると考えます。\n" -"*手掛かり*:関数 `Data.List.nubBy`の型を、PSCiを使用して調べてみましょう。\n" -"この関数は値同士の等価性を定義する述語関数に基づいてリストから重複要素を削除" -"します。\n" -"なお、それぞれの重複する項目の集合における最初の要素(リストの先頭に最も近" -"い)が保持する項目です。" +"(難しい)「重複」している住所録の項目を削除する関数`removeDuplicates`を書いてみましょう。\n" +"項目が同じ姓名を共有していれば`address`フィールドに関係なく、項目が重複していると考えます。\n" +"*手掛かり*:`Data.List.nubByEq`関数の型をPSCiを使って調べましょう。\n" +"この関数は等価性の述語に基づいてリストから重複要素を削除します。\n" +"なお、それぞれの重複する項目の集合において最初の要素(リストの先頭に最も近い)が保持する項目です。" #. type: Plain text #: text/chapter3.md:725 -#, fuzzy -#| msgid "" -#| "In this chapter, we covered several new functional programming concepts:" msgid "" "In this chapter, we covered several new functional programming concepts and " "learned how to:" -msgstr "この章では、関数型プログラミングの新しい概念を幾つも導入しました。" +msgstr "この章では関数型プログラミングの新しい概念を幾つか押さえ、以下の方法を学びました。" #. type: Bullet: '- ' #: text/chapter3.md:733 -#, fuzzy -#| msgid "" -#| "How to use the interactive mode PSCi to experiment with functions and " -#| "test ideas." msgid "" "Use the interactive mode PSCi to experiment with functions and test ideas." -msgstr "" -"対話的モードのPSCiを使用して、関数を調べるなどの思いついたことを試す方法" +msgstr "対話的モードのPSCiを使用して、関数で実験したり思いついたことを試したりする。" #. type: Bullet: '- ' #: text/chapter3.md:733 -#, fuzzy -#| msgid "" -#| "The role of types as both a correctness tool, and an implementation tool." msgid "Use types as both a correctness tool and an implementation tool." -msgstr "検証や実装の道具としての型の役割" +msgstr "正確さのための道具として、また実装のための道具として型を使う。" #. type: Bullet: '- ' #: text/chapter3.md:733 -#, fuzzy -#| msgid "" -#| "The use of curried functions to represent functions of multiple arguments." msgid "Use curried functions to represent functions of multiple arguments." -msgstr "多引数関数を表現する、カリー化された関数の使用" +msgstr "多引数の関数を表現するためにカリー化された関数を使う。" #. type: Bullet: '- ' #: text/chapter3.md:733 -#, fuzzy -#| msgid "Creating programs from smaller components by composition." msgid "Create programs from smaller components by composition." -msgstr "関数合成で小さな部品を組み合わせてのプログラムの構築" +msgstr "合成により小さな部品からプログラムを作る。" #. type: Bullet: '- ' #: text/chapter3.md:733 -#, fuzzy -#| msgid "Structuring code neatly using `where` expressions." msgid "Structure code neatly using `where` expressions." -msgstr "`where`節を利用したコードの構造化" +msgstr "`where`式を使ってコードを手際良く構造化する。" #. type: Bullet: '- ' #: text/chapter3.md:733 -#, fuzzy -#| msgid "How to avoid null values by using the `Maybe` type." msgid "Avoid null values by using the `Maybe` type." -msgstr "`Maybe`型を使用してnull値を回避する方法" +msgstr "`Maybe`型を使用してnull値を回避する。" #. type: Bullet: '- ' #: text/chapter3.md:733 -#, fuzzy -#| msgid "" -#| "Using techniques like eta conversion and function composition to refactor " -#| "code into a clear specification." msgid "" "Use techniques like eta conversion and function composition to refactor code " "into a clear specification." -msgstr "" -"イータ変換や関数合成のような手法を利用した、よりわかりやすいコードへの再構成" +msgstr "イータ変換や関数合成のような技法を使ってより分かりやすい仕様にリファクタする。" #. type: Plain text #: text/chapter3.md:734 @@ -20980,12 +20626,6 @@ msgstr "それ以外の場合、関数は最後の行の式を評価して返し #. type: Plain text #: text/chapter5.md:54 #, fuzzy -#| msgid "" -#| "Note that patterns can bind values to names - each line in the example " -#| "binds one or both of the names `n` and `m` to the input values. As we " -#| "learn about different kinds of patterns, we will see that different types " -#| "of patterns correspond to different ways to choose names from the input " -#| "arguments." msgid "" "Note that patterns can bind values to names – each line in the example binds " "one or both of the names `n` and `m` to the input values. As we learn about " @@ -20993,10 +20633,8 @@ msgid "" "different ways to choose names from the input arguments." msgstr "" "なお、パターンでは値を名前に束縛できます。\n" -"この例の各行では `n`や`m`という名前の何れかまたは両方に入力された値を束縛して" -"います。\n" -"さまざまな種類のパターンについて学んでいくうちに、それぞれの種類のパターンが" -"入力の引数から名前を選ぶさまざまな方法に対応することがわかるでしょう。" +"この例の各行では `n`や`m`という名前の何れかまたは両方に入力された値を束縛しています。\n" +"様々な種類のパターンについて学んでいくうちに、それぞれの種類のパターンが入力の引数から名前を選ぶ様々な方法に対応することがわかるでしょう。" #. type: Title ## #: text/chapter5.md:55 @@ -22147,7 +21785,7 @@ msgid "" "Here is its definition from the `maybe` package:" msgstr "" "それではPureScriptの標準ライブラリから別の例を見てみましょう。\n" -"オプショナルな値を定義するのに使われる `Maybe`型を本書の冒頭で扱いました。\n" +"省略可能な値を定義するのに使われる `Maybe`型を本書の冒頭で扱いました。\n" "`maybe`パッケージでは `Maybe`を次のように定義しています。" #. type: Fenced code block (haskell) @@ -22875,7 +22513,7 @@ msgstr "" msgid "" "`maybe`, which defines the `Maybe` data type, which represents optional " "values." -msgstr "`maybe`: オプショナルな値を表す `Maybe`データ型が定義されています。" +msgstr "`maybe`: 省略可能な値を表す `Maybe`データ型が定義されています。" #. type: Bullet: '- ' #: text/chapter6.md:24 @@ -23047,9 +22685,7 @@ msgstr "" msgid "" "These examples demonstrate how to `show` values of various primitive types, " "but we can also `show` values with more complicated types:" -msgstr "" -"この例ではさまざまなプリミティブ型の値を `show`しましたが、もっと複雑な型を持" -"つ値も`show`できます。" +msgstr "この例では様々な原始型の値を `show`しましたが、もっと複雑な型を持つ値も`show`できます。" #. type: Fenced code block (text) #: text/chapter6.md:69 @@ -23911,17 +23547,11 @@ msgstr "" #. type: Plain text #: text/chapter6.md:312 #, fuzzy -#| msgid "" -#| "The second law is the _composition law_. It states that mapping one " -#| "function over a structure, and then mapping a second, is the same thing " -#| "as mapping the composition of the two functions over the structure." msgid "" "The second law is the _composition law_. It states that mapping one function " "over a structure and then mapping a second is the same as mapping the " "composition of the two functions over the structure." -msgstr "" -"第二の法則は _合成律_ (composition law) です。構造を1つの関数で写してから2つ" -"めの関数で写すのは、2つの関数の合成で構造を写すのと同じだ、と言っています。" +msgstr "第2の法則は _合成律_ (composition law) です。構造を1つの関数で写してから2つめの関数で写すのは、2つの関数の合成で構造を写すのと同じだ、と言っています。" #. type: Plain text #: text/chapter6.md:314 @@ -26129,10 +25759,7 @@ msgstr "" msgid "" "This type class instance says that we can apply an optional function to an " "optional value, and the result is defined only if both are defined." -msgstr "" -"この型クラスのインスタンスで書かれているのは、任意のオプショナルな値にオプ" -"ショナルな関数を適用でき、その両方が定義されている時に限り結果も定義される、" -"ということです。" +msgstr "この型クラスのインスタンスで書かれているのは、任意の省略可能な値に省略可能な関数を適用でき、その両方が定義されている時に限り結果も定義される、ということです。" #. type: Plain text #: text/chapter7.md:129 @@ -26364,10 +25991,9 @@ msgstr "" #. type: Plain text #: text/chapter7.md:205 #, fuzzy, no-wrap -#| msgid "As an example, the functor `Maybe` represents the side effect of possibly-missing values. Some other examples include `Either err`, which represents the side effect of possible errors of type `err`, and the arrow functor `r ->` which represents the side-effect of reading from a global configuration. For now, we'll only consider the `Maybe` functor.\n" msgid "As an example, the functor `Maybe` represents the side effect of possibly-missing values. Some other examples include `Either err`, which represents the side effect of possible errors of type `err`, and the arrow functor `r ->`, which represents the side-effect of reading from a global configuration. For now, we'll only consider the `Maybe` functor.\n" msgstr "" -"例えば関手`Maybe`はオプショナルな値の副作用を表現しています。\n" +"例えば関手`Maybe`は省略可能な値の副作用を表現しています。\n" "その他の例としては、型`err`のエラーの可能性の副作用を表す`Either err`や、大域的な構成を読み取る副作用を表すArrow関手 (arrow functor) `r ->`があります。\n" "ここでは`Maybe`関手についてのみ考えることにします。\n" @@ -26597,10 +26223,8 @@ msgid "" "convert optional inputs into computations which can signal an error using " "`Either String`:" msgstr "" -"`Meybe`上へ持ち上げる代わりに`Either String`上へ持ち上げるようにすると、エ" -"ラーメッセージを返すことができるようになります。\n" -"まずは`Either String`を使ってオプショナルな入力をエラーを発信できる計算に変換" -"する演算子を書きましょう。" +"`Meybe`上へ持ち上げる代わりに`Either String`上へ持ち上げるようにすると、エラー文言を返せるようになります。\n" +"まずは`Either String`を使い、省略可能な入力からエラーを発信できる計算に変換する演算子を書きましょう。" #. type: Fenced code block (text) #: text/chapter7.md:270 @@ -26912,12 +26536,6 @@ msgstr "" #. type: Plain text #: text/chapter7.md:376 #, fuzzy -#| msgid "" -#| "When specialized to `Maybe`, our function returns a `Just` only if every " -#| "list element was `Just`, otherwise it returns `Nothing`. This is " -#| "consistent with our intuition of working in a larger language supporting " -#| "optional values - a list of computations which return optional results " -#| "only has a result itself if every computation contained a result." msgid "" "When specialized to `Maybe`, our function returns a `Just` only if every " "list element is `Just`; otherwise, it returns `Nothing`. This is consistent " @@ -26925,12 +26543,9 @@ msgid "" "values – a list of computations that produce optional results only has a " "result itself if every computation contained a result." msgstr "" -"`Meybe`へ特殊化して考えると、リストの全ての要素が`Just`であるときに限りこの関" -"数は`Just`を返しますし、そうでなければ`Nothing`を返します。\n" -"これはオプショナルな値に対応する、より大きな言語に取り組む上での直感から一貫" -"しています。\n" -"オプショナルな結果を返す計算のリストは、全ての計算が結果を持っているならばそ" -"れ自身の結果のみを持つのです。" +"`Meybe`へ特殊化して考えると、リストの全ての要素が`Just`であるときに限りこの関数は`Just`を返しますし、そうでなければ`Nothing`を返します。\n" +"これは省略可能な値に対応する、より大きな言語に取り組む上での直感から一貫しています。\n" +"省略可能な結果を返す計算のリストは、全ての計算が結果を持っているならばそれ自身の結果のみを持つのです。" #. type: Plain text #: text/chapter7.md:378 @@ -26957,21 +26572,14 @@ msgstr "" #. type: Bullet: ' 1. ' #: text/chapter7.md:386 #, fuzzy -#| msgid "" -#| "(Medium) Write versions of the numeric operators `+`, `-`, `*` and `/` " -#| "which work with optional arguments (i.e. arguments wrapped in `Maybe`) " -#| "and return a value wrapped in `Maybe`. Name these functions `addMaybe`, " -#| "`subMaybe`, `mulMaybe`, and `divMaybe`. _Hint_: Use `lift2`." msgid "" "(Medium) Write versions of the numeric operators `+`, `-`, `*`, and `/` " "which work with optional arguments (i.e., arguments wrapped in `Maybe`) and " "return a value wrapped in `Maybe`. Name these functions `addMaybe`, " "`subMaybe`, `mulMaybe`, and `divMaybe`. _Hint_: Use `lift2`." msgstr "" -"(普通)数値演算子`+`、`-`、`*`、`/`のオプショナル引数(つまり`Maybe`に包まれ" -"た引数)を扱って`Maybe`に包まれた値を返す版を書いてください。\n" -"これらの関数には`addMaybe`、`subMaybe`、`mulMaybe`、`divMaybe`と名前を付けま" -"す。\n" +"(普通)数値演算子`+`、`-`、`*`、`/`の省略可能な引数(つまり`Maybe`に包まれた引数)を扱って`Maybe`に包まれた値を返す版を書いてください。\n" +"これらの関数には`addMaybe`、`subMaybe`、`mulMaybe`、`divMaybe`と名前を付けます。\n" "*手掛かり*:`lift2`を使ってください。" #. type: Bullet: ' 1. ' @@ -26989,22 +26597,15 @@ msgstr "" #. type: Bullet: ' 1. ' #: text/chapter7.md:386 #, fuzzy -#| msgid "" -#| "(Difficult) Write a function `combineMaybe` which has type `forall a f. " -#| "Applicative f => Maybe (f a) -> f (Maybe a)`. This function takes an " -#| "optional computation with side-effects, and returns a side-effecting " -#| "computation which has an optional result." msgid "" "(Difficult) Write a function `combineMaybe` which has type `forall a f. " "Applicative f => Maybe (f a) -> f (Maybe a)`. This function takes an " "optional computation with side-effects and returns a side-effecting " "computation with an optional result." msgstr "" -"(難しい)型`combineMaybe : forall a f. (Applicative f) => Maybe (f a) -> f " -"(Maybe a)`\n" +"(難しい)型`combineMaybe : forall a f. (Applicative f) => Maybe (f a) -> f (Maybe a)`\n" "を持つ関数`combineMaybe`を書いてください。\n" -"この関数は副作用をもつオプショナルな計算をとり、オプショナルな結果をもつ副作" -"用のある計算を返します。" +"この関数は副作用をもつ省略可能な計算をとり、省略可能な結果をもつ副作用のある計算を返します。" #. type: Plain text #: text/chapter7.md:390 @@ -27813,12 +27414,6 @@ msgstr "" #. type: Plain text #: text/chapter7.md:639 #, fuzzy -#| msgid "" -#| "These examples show that traversing the `Nothing` value returns `Nothing` " -#| "with no validation, and traversing `Just x` uses the validation function " -#| "to validate `x`. That is, `traverse` takes a validation function for type " -#| "`a` and returns a validation function for `Maybe a`, i.e. a validation " -#| "function for optional values of type `a`." msgid "" "These examples show that traversing the `Nothing` value returns `Nothing` " "with no validation, and traversing `Just x` uses the validation function to " @@ -27826,10 +27421,8 @@ msgid "" "and returns a validation function for `Maybe a`, i.e., a validation function " "for optional values of type `a`." msgstr "" -"これらの例では、`Nothing`の値の走査は検証なしで`Nothing`の値を返し、`Just x`" -"を走査すると`x`を検証するのに検証関数が使われるということを示しています。\n" -"要は、`traverse`は型`a`についての検証関数をとり、`Maybe a`についての検証関" -"数、つまり型`a`のオプショナルな値についての検証関数を返すのです。" +"これらの例では、`Nothing`の値の走査は検証なしで`Nothing`の値を返し、`Just x`を走査すると`x`を検証するのに検証関数が使われるということを示しています。\n" +"要は、`traverse`は型`a`についての検証関数をとり、`Maybe a`についての検証関数、つまり型`a`の省略可能な値についての検証関数を返すのです。" #. type: Plain text #: text/chapter7.md:641 @@ -27964,10 +27557,8 @@ msgid "" "this new `Person`. _Hint_: Use `traverse` to validate a field of type `Maybe " "a`." msgstr "" -"(普通)`homeAddress`フィールドがオプショナル(`Maybe`を使用)な新しい版の" -"`Person`型をつくってください。\n" -"それからこの新しい`Person`を検証する新しい版の`validatePerson`" -"(`validatePersonOptionalAddress`と改名します)を書いてください。\n" +"(普通)`homeAddress`フィールドが省略可能(`Maybe`を使用)な新しい版の`Person`型をつくってください。\n" +"それからこの新しい`Person`を検証する新しい版の`validatePerson`(`validatePersonOptionalAddress`と改名します)を書いてください。\n" "*手掛かり*:`traverse`を使って型`Maybe a`のフィールドを検証してください。" #. type: Bullet: ' 1. ' @@ -28202,20 +27793,14 @@ msgstr "作用モナド" #. type: Plain text #: text/chapter8.md:6 #, fuzzy -#| msgid "" -#| "In the last chapter, we introduced applicative functors, an abstraction " -#| "which we used to deal with _side-effects_: optional values, error " -#| "messages and validation. This chapter will introduce another abstraction " -#| "for dealing with side-effects in a more expressive way: _monads_." msgid "" "In the last chapter, we introduced applicative functors, an abstraction we " "used to deal with _side-effects_: optional values, error messages, and " "validation. This chapter will introduce another abstraction for dealing with " "side-effects more expressively: _monads_." msgstr "" -"前章では、オプショナルな型やエラーメッセージ、データの検証など、 _副作用_ を" -"扱いを抽象化するアプリカティブ関手を導入しました。この章では、より表現力の高" -"い方法で副作用を扱うための別の抽象化、 _モナド_ を導入します。" +"前章では、省略可能な型やエラー文言、データの検証など、*副作用*を扱いを抽象化するアプリカティブ関手を導入しました。\n" +"この章では、より表現力の高い方法で副作用を扱うための別の抽象化、*モナド*を導入します。" #. type: Plain text #: text/chapter8.md:8 @@ -28374,12 +27959,8 @@ msgid "" "the _array monad_, embedding PureScript functions into a larger programming " "language supporting _non-deterministic choice_." msgstr "" -"前の章では、*オプショナルな値*に対応したより大きなプログラミング言語へと" -"PureScriptの関数を埋め込む、`Maybe`アプリカティブ関手についての直感的理解を養" -"いました。\n" -"同様に*配列モナド*についても、*非決定選択*に対応したより大きなプログラミング" -"言語へPureScriptの関数を埋め込む、というような直感的理解を得ることができま" -"す。" +"前の章では、*省略可能な値*に対応したより大きなプログラミング言語へとPureScriptの関数を埋め込む、`Maybe`アプリカティブ関手についての直感的理解を養いました。\n" +"同様に*配列モナド*についても、*非決定選択*に対応したより大きなプログラミング言語へPureScriptの関数を埋め込む、というような直感的理解を得ることができます。" #. type: Plain text #: text/chapter8.md:52 @@ -28965,26 +28546,18 @@ msgstr "" msgid "" "Intuitively, `foldM` performs a fold over a list in some context supporting " "some set of side-effects." -msgstr "" -"直感的には、 `foldM`はさまざまな副作用の組み合わせに対応した文脈での配列の畳" -"み込みを行うと捉えることができます。" +msgstr "直感的には、`foldM`は様々な副作用の組み合わせに対応した文脈で配列を畳み込むものと捉えられます。" #. type: Plain text #: text/chapter8.md:225 #, fuzzy -#| msgid "" -#| "For example, if we picked `m` to be `Maybe`, then our fold would be " -#| "allowed to fail by returning `Nothing` at any stage - every step returns " -#| "an optional result, and the result of the fold is therefore also optional." msgid "" "For example, if we picked `m` to be `Maybe`, then our fold would be allowed " "to fail by returning `Nothing` at any stage – every step returns an optional " "result, and the result of the fold is therefore also optional." msgstr "" -"例として `m`が `Maybe`であるとすると、この畳み込みはそれぞれの段階で " -"`Nothing`を返すことで失敗させられます。\n" -"それぞれの段階ではオプショナルな結果を返しますから、それゆえ畳み込みの結果も" -"オプショナルになります。" +"例として `m`が `Maybe`であるとすると、この畳み込みはそれぞれの段階で `Nothing`を返すことで失敗させられます。\n" +"それぞれの段階では省略可能な結果を返しますから、それゆえ畳み込みの結果も省略可能になります。" #. type: Plain text #: text/chapter8.md:227 @@ -30716,12 +30289,6 @@ msgstr "" #. type: Plain text #: text/chapter8.md:698 #, fuzzy -#| msgid "" -#| "We are going to build a form which will allow a user to add a new entry " -#| "into our address book. The form will contain text boxes for the various " -#| "fields (first name, last name, city, state, etc.), and an area in which " -#| "validation errors will be displayed. As the user types text into the text " -#| "boxes, the validation errors will be updated." msgid "" "We are going to build a form that will allow a user to add a new entry into " "our address book. The form will contain text boxes for the various fields " @@ -30730,8 +30297,7 @@ msgid "" "validation errors will be updated." msgstr "" "利用者が住所録に新しい項目を追加できるフォームを構築することにしましょう。\n" -"フォームには、さまざまなフィールド(姓、名前、都市、州など)のテキストボック" -"ス、及び検証エラーが表示される領域が含まれます。\n" +"フォームには、様々なフィールド(姓、名前、都市、州など)のテキストボックス、及び検証エラーが表示される領域が含まれます。\n" "テキストボックスに利用者がテキストを入力すると、検証エラーが更新されます。" #. type: Plain text @@ -31761,9 +31327,7 @@ msgid "" "We used the `Effect` monad to handle a variety of effects: random number " "generation, exceptions, console IO, mutable state, and DOM manipulation " "using React." -msgstr "" -"乱数生成、例外、コンソール入出力、変更可能な状態、及びReactを使ったDOM操作と" -"いった、さまざまな作用を扱うために `Effect`モナドを使いました。" +msgstr "乱数生成、例外、コンソール入出力、変更可能な状態、及びReactを使ったDOM操作といった、様々な作用を扱うために `Effect`モナドを使いました。" #. type: Plain text #: text/chapter8.md:1012 diff --git a/translation/terms.txt b/translation/terms.txt index 57945f69..b39e68fc 100644 --- a/translation/terms.txt +++ b/translation/terms.txt @@ -1 +1,3 @@ primitive type: 原始型 +type synonym: 型同義語 +optional: 省略可能な