Help us understand the problem. What is going on with this article?

PureScript by Example 4 章の前半を読む

More than 3 years have passed since last update.

この記事は (bouzuya) PureScript Advent Calendar 2016 の 10 日目。 (bouzuya) PureScript Advent Calendar 2016 は bouzuya の PureScript 学習の記録だ。

概要

PureScript by ExamplePureScript Language Guide を見ながら進めていく。今日は PureScript by Example の 4 章 の前半を読む。

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

PureScript 4.1

4 章は再帰関数を扱うようだ。 map fold filter concatMap は少なくとも登場するらしい。

例としては仮想のファイルシステムを扱う。ツリー構造を再帰かな……。

PureScript 4.2

今回のプロジェクトでは次のものをインストールするらしい。また Data.Path という使うだけのモジュールが必要らしい。資料を置いてあるリポジトリを参照すると良い。なぜ、いままでも使ってきた purescript-console をいまさらと思う。

  • purescript-maybe
  • purescript-arrays
  • purescript-strings
  • purescript-foldable-traversable
  • purescript-console

Pursuit:

PureScript by Example 4.3

再帰は重要。可変な状態を減らすことを助ける。なるほど。

再帰は分割統治と関係がある。ふむ。

fact :: Int -> Int
fact 0 = 1
fact n = n * fact (n - 1)

fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

それぞれの場合ごとに考えてつくっていけるってことかな。

PureScript by Example 4.4

配列の再帰。 length の例。 nullArray が空かを判定して、そうでなければ taillength で……という感じ。ふむり。

module Main where

import Prelude

import Data.Array (null)
import Data.Array.Partial (tail)
import Partial.Unsafe (unsafePartial)

length :: forall a. Array a -> Int
length arr =
  if null arr
    then 0
    else 1 + length (unsafePartial tail arr)

Pursuit:

そういえば if ... then ... else は初出なのかな。

unsafePartial は説明がないので、またそのうち出てくるはず。あと直接の依存関係にないのだけど、たぶん、purescript-arrays からの間接的な依存関係に入っているはず……。

PureScript by Example 4.5

map

> import Prelude (map)
> map (\n -> n + 1) [1, 2, 3, 4, 5]
[2,3,4,5,6]

> :type map
forall a b f. (Functor f) => (a -> b) -> f a -> f b

JavaScript の Array.prototype.map と動きは似ているけど、こちらは Prelude に入っているし、Array 以外でも (Functor なら) 使える。その説明は出ていないけど、そのうち出てくるはず。過去に AddressBook のところで Maybe が出てきたときに、使っていた気もする。

あと <$>map の operator alias (これも書いたはず) 。

Pursuit:

PureScript by Example 4.6

Infix Operator 。あれ、前もやったような……。中置演算子や中置関数適用 (infix function application) か。

> (\n -> n + 1) `map` [1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]

> (\n -> n + 1) <$> [1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]

> :type map
forall a b f. (Functor f) => (a -> b) -> f a -> f b

言ってるそばから <$>:type map が出てきた。

演算子を関数的に使う方法も前回書いたような気がする。

> import Prelude (map, show, (<$>))
> show <$> [1, 2, 3, 4, 5]
["1","2","3","4","5"]

> (<$>) show [1, 2, 3, 4, 5]
["1","2","3","4","5"]

range の operator alias である (..) を使ってみるらしい。

> import Data.Array ((..))
> 1 .. 5
[1,2,3,4,5]

> import Prelude (show, (<$>))
> show <$> (1 .. 5)
["1","2","3","4","5"]

Pursuit:

(..) の定義は次のようにするらしい。

infix 8 range as ..

ソースコードを見てみた。確かに。 https://github.com/purescript/purescript-arrays/blob/v3.1.0/src/Data/Array.purs#L161

PureScript by Example 4.7

filter 。 JavaScript の Array.prototype.filter はおなじみのはずなので、特に説明は不要かな。

> import Prelude (mod, (==))
> import Data.Array (filter, (..))
> filter (\n -> n `mod` 2 == 0) (1 .. 10)
[2,4,6,8,10]

> :t filter
forall a. (a -> Boolean) -> Array a -> Array a

Pursuit:

PureScript by Example 4.8

concat 。 JavaScript の Array.prototype.concat とは違い、flatten っぽい動き。

> import Data.Array (concat)
> :t concat
forall a. Array (Array a) -> Array a

> concat [[1, 2, 3], [4, 5], [6]]
[1,2,3,4,5,6]

Pursuit:

concatMap

> import Prelude ((*))
> import Data.Array (concatMap, (..))

> :t concatMap
forall a b. (a -> Array b) -> Array a -> Array b

> concatMap (\n -> [n, n * n]) (1 .. 5)
[1,1,2,4,3,9,4,16,5,25]

map して concat する感じ。語順のイメージは↓の concat $ map ... からだと思う。

> import Prelude (map, ($))
> concat (map (\n -> [n, n * n]) (1 .. 5))
[1,1,2,4,3,9,4,16,5,25]

> concat $ map (\n -> [n, n * n]) (1 .. 5)
[1,1,2,4,3,9,4,16,5,25]

Pursuit:

PureScript by Example 4.9

配列内包 (array comprehensions) 。因数を見つける関数を書くようだ。

まずは組み合わせを列挙するらしい。

> let pairs n = concatMap (\i -> 1 .. n) (1 .. n)
> pairs 3
[1,2,3,1,2,3,1,2,3]

> let pairs' n = concatMap (\i -> map (\j -> [i, j]) (1 .. n)) (1 .. n)
> pairs' 3
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]

> let pairs'' n = concatMap (\i -> map (\j -> [i, j]) (i .. n)) (1 .. n)
> pairs' 3
[[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
> import Prelude (map, (==))
> import Data.Array (concatMap, filter, (..))
> import Data.Foldable (product)
> let pairs'' n = concatMap (\i -> map (\j -> [i, j]) (i .. n)) (1 .. n)
> let factors n = filter (\pair -> product pair == n) (pairs'' n)
> factors 10
[[1,10],[2,5]]

product はソースによると foldl (*) oneoneSemiring のもの。

https://github.com/purescript/purescript-foldable-traversable/blob/v2.0.0/src/Data/Foldable.purs#L255

Pursuit:

まとめ

再帰関数。個人的には特にはまることなく、とんとんと進んだ。次は後半。

参考

bouzuya
ぼく、ぼうずや。なさけはひとのためならず。たのしいはせいぎ。
http://bouzuya.net/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした