Edited at

オンライン版『Real World Haskell』読書会 2019年1月30日

本記事は、内々で行っている「オンライン版『Real World Haskell』読書会」のための資料です。

本記事に含まれている引用部分は、オンライン版『Real World Haskell』からの引用であり、ライセンス表記は以下の通りです。


Copyright 2007, 2008 Bryan O'Sullivan, Don Stewart, and John Goerzen. This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 License.


本記事の引用以外の部分は筆者による超訳であり、ライセンスは原著と同様「CC BY-NC 3.0」とします。

今回の範囲は「Chapter 2. Types and Functions」の「What to expect from the type system」から「Function application」までです。

強調表示」となっている箇所は、翻訳に自信のない箇所です。


What to expect from the type system / 型システムに期待するもの


Our exploration of the major capabilities and benefits of Haskell's type system will span a number of chapters. Early on, you may find Haskell's types to be a chore to deal with.


これからいくつかの章に渡り、Haskellの型システムの主な能力と利点について探求していきます。

それらの早い段階で、Haskellの型システムを扱うことが面倒だと思うかもしれません。


  • chore [n.] /tʃɔː $ tʃɔːr/: 雑用、はんぱ仕事、(家庭や農場の)雑仕事、面倒な仕事


For example, instead of simply writing some code and running it to see if it works as you might expect in Python or Ruby, you'll first need to make sure that your program passes the scrutiny of the type checker. Why stick with the learning curve?


例えば、PythonやRubyを使って単にコードを書き、期待通りに動作するかどうかを確認する代わりに、あなたのプログラムが型チェッカによる精密な検査に合格するかどうか、はじめに確かめる必要があります。

学習曲線になぜこだわる?


  • scrutiny [n.] /ˈskruːtɪni/: 精密な調査、じろじろ見ること、投票(再)検査


While strong, static typing makes Haskell safe, type inference makes it concise. The result is potent: we end up with a language that's both safer than popular statically typed languages, and often more expressive than dynamically typed languages. This is a strong claim to make, and we will back it up with evidence throughout the book.


強くて静的な型付けはHaskellに安全をもたらし、型推論はそれを簡潔にします。

その結果、人気のある静的型付け言語より安全で、動的型付け言語より表現力がある言語になりました。

これは強い主張であり、この本を通して根拠と共に裏付けていきます。


  • concise [adj.] /kənˈsaɪs/: 簡潔な、簡明な

  • potent [adj.] /ˈpəʊtənt $ ˈpoʊ-/: 効能のある、人を信服させる、説得力のある、性的能力のある、有力な、勢力のある


Fixing type errors may initially feel like more work than if you were using a dynamic language. It might help to look at this as moving much of your debugging up front. The compiler shows you many of the logical flaws in your code, instead of leaving you to stumble across problems at runtime.


最初は、型に関するエラーを修正することを、動的な言語を使う場合と比べて大変だと感じるかも知れません。

それは、デバッグ作業の大部分を前もって行っていると見ることができます。

コンパイラは、実行時に問題に遭遇することを避けるため、コードの論理的な欠陥の多くをあなたに示します。


  • up front [adv./adj.] /ˌʌpˈfrʌnt◂/: フロントコートで、フォワードの位置で、前もって、前金で、正直に、腹蔵なく

  • flaws, flaw [n.] /flɔː $ flɒː/: きず、ひび、割れ目、欠点、弱点、不備な点、欠陥、突風、ひとしきりのあらし

  • stumble [i.v.] /ˈstʌmbəl/: つまずく、よろめく、(…に)つまずく、よろめき歩く、よろよろしながら行く、(…に)どもる、とちる、つかえる、(…に)偶然出合う、ひょっこり気づく


Furthermore, because Haskell can infer the types of your expressions and functions, you gain the benefits of static typing without the added burden of “finger typing” imposed by less powerful statically typed languages. In other languages, the type system serves the needs of the compiler. In Haskell, it serves you. The tradeoff is that you have to learn to work within the framework it provides.


その上、Haskellは式や関数の型を推論することができるため、あまり強力ではない静的型付け言語におけるタイピングのような負荷を伴うことなく、静的型付けの利点を得ることができます。

他の言語では、型システムはコンパイラからの要求に仕えます。

Haskellでは、型システムはあなたに仕えます。

そのトレードオフは、型システムが提供する枠組みとともに仕事をすることを覚える必要があることです。


  • Furthermore [adv.] /ˌfɜːðəˈmɔː $ ˈfɜːrðərmɔːr/: なお、そのうえ、さらに


We will introduce new uses of Haskell's types throughout this book, to help us to write and test practical code. As a result, the complete picture of why the type system is worthwhile will emerge gradually. While each step should justify itself, the whole will end up greater than the sum of its parts.


この本を通じてHaskellの型の新しい使い道を紹介することで、実践的なコードを書き、テストすることを助けます。

その結果として、「なぜ型システムが時間をかける価値があるものか」の全体像が徐々に浮かび上がるでしょう。

それぞれの段階は、それ自身を正当化するべきあると同時に、個々の合計より全体が大きくなります。


  • worthwhile [adj.] /ˌwɜːθˈwaɪl◂ $ ˌwɜːrθ-/: 時間と労力をかけるだけの値打ちのある、やりがいのある


Some common basic types / いくつかの基本的な型


In the section called “First steps with types”, we introduced a few types. Here are several more of the most common base types.


「First steps with types」という節では、いくつかの型を紹介しました。

この節では、さらにいくつかの基本となる型を紹介します。



  • A Char value represents a Unicode character.




  • Char値は、単一のUnicode文字を表現します。



  • A Bool value represents a value in Boolean logic. The possible values of type Bool are True and False.




  • Bool値は真偽値を表現します。Boolの取り得る値はTrueFalseです。



  • The Int type is used for signed, fixed-width integer values. The exact range of values representable as Int depends on the system's longest “native” integer: on a 32-bit machine, an Int is usually 32 bits wide, while on a 64-bit machine, it is usually 64 bits wide. The Haskell standard only guarantees that an Int is wider than 28 bits. (There exist numeric types that are exactly 8, 16, and so on bits wide, in signed and unsigned flavours; we'll get to those later.)




  • Int型は符号付きで固定ビット幅の整数値に使われます。
    この型が表現する値の範囲は、「システムが持つ最も長いネイティブな整数型」に依存します。32ビットマシンでは通常32ビットの幅を持ち、64ビットマシンでは通常64ビットの幅を持ちます。
    Haskellの標準規格では、Intは28ビットより大きい幅を持つことだけを保証します。
    (8ビット、16ビット以上の幅を持つ符号付き数値型、符号なし数値型も存在し、後述します。)



  • An Integer value is a signed integer of unbounded size. Integers are not used as often as Ints, because they are more expensive both in performance and space consumption. On the other hand, Integer computations do not silently overflow, so they give more reliably correct answers.




  • Integer値は無制限のサイズを持つ符号付き整数です。
    Integerはパフォーマンスとメモリ使用量のコストが高いため、Intほど頻繁には使われません。
    一方で、Integerを使った計算はオーバーフローが発生することがなく、確実に正しい答えを提供してくれます。



  • Values of type Double are used for floating point numbers. A Double value is typically 64 bits wide, and uses the system's native floating point representation. (A narrower type, Float, also exists, but its use is discouraged; Haskell compiler writers concentrate more on making Double efficient, so Float is much slower.)




  • Double型は、浮動小数点数に使われます。
    Double値は通常64ビット幅で、システムが持つネイティブな浮動小数点数表現が使われます。
    (よりビット幅の小さいFloat型も存在しますが、Haskellコンパイラの作者たちはDouble型をより効率的にすることに集中しており、Float型は遅いため、使うことをおすすめしません)


We have already briefly seen Haskell's notation for types in the section called “First steps with types”. When we write a type explicitly, we use the notation expression :: MyType to say that expression has the type MyType. If we omit the :: and the type that follows, a Haskell compiler will infer the type of the expression.


Haskellの型表記については「First steps with types」という節で、簡単に説明しました。

型を明示的に記述する時、「expression式はMyType型を持つ」ことを伝えるためexpression :: MyTypeという表記を用います。

::とそれに続く型を省略すると、Haskellコンパイラは式の型を推論します。

ghci> :type 'a'

'a' :: Char
ghci> 'a' :: Char
'a'
ghci> [1,2,3] :: Int

<interactive>:1:0:
Couldn't match expected type `Int' against inferred type `[a]'
In the expression: [1, 2, 3] :: Int
In the definition of `it': it = [1, 2, 3] :: Int


The combination of :: and the type after it is called a type signature.


::とそれに続く型の組み合わせは「型シグネチャ」(type signature)と呼ばれます。


Function application / 関数適用


Now that we've had our fill of data types for a while, let's turn our attention to working with some of the types we've seen, using functions.


ここまでしばしの間、データ型について学んできました。ここからは、関数を使って、これまで見てきた型を処理することに注目しましょう。


To apply a function in Haskell, we write the name of the function followed by its arguments.


Haskellにおいて「関数を適用する」には、関数名とその引数を続けて書きます。

ghci> odd 3

True
ghci> odd 6
False


We don't use parentheses or commas to group or separate the arguments to a function; merely writing the name of the function, followed by each argument in turn, is enough. As an example, let's apply the compare function, which takes two arguments.


引数をグループ化したり区切るために丸括弧やカンマを書く必要はありません。単に関数名を書き、それに続けて引数を書くだけで十分です。

具体例として、2つの引数を取るcompare(比較)関数を適用してみましょう。

ghci> compare 2 3

LT
ghci> compare 3 3
EQ
ghci> compare 3 2
GT


If you're used to function call syntax in other languages, this notation can take a little getting used to, but it's simple and uniform.


他の言語の関数呼び出し記法に慣れているなら、この記法に慣れるのに少し時間がかかるかもしれません。

でもそれはシンプルで均一です。


Function application has higher precedence than using operators, so the following two expressions have the same meaning.


関数適用は、演算子の使用よりも高い優先順位を持つため、以下の2つの式は同じ意味を持ちます。


  • precedence [n.] /ˈpresɪdəns/: (時間・順序などが)先立つこと、先行、先任、上位、優先(権)


    • 似た言葉: president [n.] /ˈprezɪdənt/: (共和国の)大統領、(官庁の)総裁、(大学の)学長、総長、(学術会議・協会などの)会長、(銀行・会社の)頭取、社長、座長、司会者



ghci> (compare 2 3) == LT

True
ghci> compare 2 3 == LT
True


The above parentheses don't do any harm, but they add some visual noise. Sometimes, however, we must use parentheses to indicate how we want a complicated expression to be parsed.


上記の丸括弧は害を及ぼしませんが、幾分かの視覚的なノイズを与えてしまいます。

しかしながら、複雑な式をどうパースするかを示すために、時折、丸括弧を使わなければなりません。

ghci> compare (sqrt 3) (sqrt 6)

LT


This applies compare to the results of applying sqrt 3 and sqrt 6, respectively. If we omit the parentheses, it looks like we are trying to pass four arguments to compare, instead of the two it accepts.


上記の例は、sqrt 3sqrt 6をそれぞれ適用した結果をcompareに適用します。

もし丸括弧を省略した場合、compareが受け付ける「2つの引数」ではなく「4つの引数」を渡そうとしているように見えます。


Useful composite data types: lists and tuples

...