LoginSignup
0
2

More than 5 years have passed since last update.

PureScript by Example 3 章の前半を読む

Last updated at Posted at 2016-12-07

この記事は (bouzuya) PureScript Advent Calendar 2016 の 7 日目です。 (bouzuya) PureScript Advent Calendar 2016 は bouzuya の PureScript 学習の記録です。

概要

昨日に続き PureScript by ExamplePureScript Language Guide を見ながら進めていきます。今日は PureScript by Example の 3 章 の前半を読みます。

※注意事項: 英語と日本語訳では大きな差異があります。0.10.x に対応している英語の側で進めます。

PureScript by Example 3.1

この章では、関数とレコードという PureScript の構成要素を、アドレス帳アプリケーションという例を通じて学べるようです。

PureScript by Example 3.2

コードは https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/exercises/chapter3 を参照。

import Control.Plus (empty)
import Data.List (List(..), filter, head)
import Data.Maybe (Maybe)

Control.Plus モジュールは purescript-control パッケージに含まれているようですね。上記のコードはこの依存関係を解決できないので、ビルドできないですね……。 https://pursuit.purescript.org/packages/purescript-control/2.0.0/docs/Control.Plus

Data.List モジュールは purescript-lists パッケージに含まれているようですね。こちらはきちんと bower install されています。 https://pursuit.purescript.org/packages/purescript-lists/3.2.1/docs/Data.List

Data.Maybe モジュールは purescript-maybe パッケージに含まれているようですね。こちらは purescript-lists パッケージからの間接的な依存でなんとかビルドできるようですが、bower install したほうが良い気がします。 https://pursuit.purescript.org/packages/purescript-maybe/2.0.1/docs/Data.Maybe

あとで Pull Request を投げてみましょうかね……。→ paf31/purescript-book は Pull Request 禁止のようです。 Issue で。

PureScript by Example 3.3

psci:type で、基本的な型に触れています。 Language Guide の Types にあります。

Primitive Types が Number / String / Boolean ですね。これはスルー。

そして Int / Array / Records と。

IntNumber とは違い、整数に限定していますね。Array は要素の型が一致してないとダメです。 Record は JavaScript の object ですね。

> chapter3@1.0.0 pulp:psci /Users/bouzuya/.ghq/github.com/paf31/purescript-book/exercises/chapter3
> pulp psci

PSCi, version 0.10.2
Type :? for help

> :type 1
Int

> :type 1.0
Number

> :type [1, 2, 3]
Array Int

> :type [true, false]
Array Boolean

> :type [1, false]
Error found:
in module $PSCI
at  line 1, column 1 - line 1, column 11

  Could not match type

    Int

  with type

    Boolean


while inferring the type of [ 1
                            , false
                            ]
in value declaration it

See https://github.com/purescript/purescript/wiki/Error-Code-TypesDoNotUnify for more information,
or to contribute content related to this error.

> let author = { name: "Phil", interests: ["Functional Programming", "JavaScript"] }
> :type author
{ name :: String
, interests :: Array String
}

> author.name
"Phil"

> author.interests
["Functional Programming","JavaScript"]

Language Guide の Tagged Unions と Newtypes は飛ばして、Functions ですね。Tagged Unions や Newtype もすぐ出てくるはず……。

> import Prelude (flip, const)
> :type flip
forall a b c. (a -> b -> c) -> b -> a -> c

> :type const
forall a b. a -> b -> a

psci:paste を見せつつ、関数定義の例のようです。

> :paste
… let
…   add :: Int -> Int -> Int
…   add x y = x + y
…
Error found:
in module $PSCI
at  line 3, column 13 - line 3, column 17

  Unknown operator (+)


See https://github.com/purescript/purescript/wiki/Error-Code-UnknownName for more information,
or to contribute content related to this error.

> import Prelude ((+))
> :paste
… let
…   add :: Int -> Int -> Int
…   add x y = x + y
…
> add 10 20
30

> import Prelude ((*))
> let mul = \x y -> x * y
> mul 10 20
200

import Prelude を限定していたので、 (+) が読まれていなかったですね。関数のリテラルである \x -> x の形式を見せる意図があったかもしれないので、ついでに mul も書いてみました。 Language Guide の Functions も置いておきます。

PureScript by Example 3.4

forall の話。Language Guide では Quantification かな。

↓の flip についている forall はこれが全称量化された型 (universally quantified type) ってことです、って説明されてますね。ぜんぜん分からないんですけど、任意の a b c について↓の型で動くってことなんじゃないですかね。

> :type flip
forall a b c. (a -> b -> c) -> b -> a -> c

たとえば a b c には IntString などがはいるので、aIntbStringcString にすると、次のようになる、と。

(Int -> String -> String) -> String -> Int -> String

余談ですけど、型のこの表記は慣れないと困りますかね……。カリー化の話とかそのうち出てくるはずなので、スルーしますけど……。

flip に関して言うと関数を受け取って第一引数と第二引数を入れ替えた関数にする関数です。

> :reset
> import Prelude ((<>), flip, show)
> flip (\n s -> show n <> s) "Ten" 10
"10Ten"

> :type show
forall a. (Show a) => a -> String

> :type (<>)
forall a. (Semigroup a) => a -> a -> a

ふむ。

showShow インスタンスを受け取って String を返す関数ですね。要するに .toString() 的なあれです。
https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Show#v:show

(<>)Semigroup インスタンスをふたつ受け取ってくっつけて返します。Array.prototype.concat 的なあれです。 (<>)append にたいしての operator alias です。これもそのうち出てくるはず……。
https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Semigroup#v:(%3C%3E)

これは書かれていますが、引数を逆にして flip (\n s -> show n <> s) 10 "Ten" にすると動きません。show 10 の結果である "10""Ten""10" <> "Ten" するから動くのであって、show "Ten" の結果である "\"Ten\""10<> することはできません。型が違いますからね。

PureScript by Example 3.5

インデントの注意。雰囲気でインデントしてますけど、大丈夫ですね……。基本は同じブロックなら同じインデント、改行できそうなところで見た目のために改行したいなら、ひとつ深くインデントしておけば大丈夫。ブロックが終わればインデントを浅くする感じですかね。文字で読んでもなんとなくピンとこないですし、ルールとして書くと難しい感じはしますけど、素朴にインデントすると動くような……。うーん。

一応 Language Guide の Whitespace Rules を貼っておきます。

まとめ

まだ 3 章の前半ですけど、疲れてきたので、今日はこのへんでおしまいです。

参考

次回以降の TODO

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2