実例による PureScript 3 章

build の前にいくつかの module のインストールが必要だった。

$ spago install purescript-control
$ spago install purescript-maybe
$ spago install purescript-lists

$ spago build

$ spago repl
> import Data.AddressBook 
> address = { street: "明治通り", city: "Shibuya", state: "Tokyo" }
> showAddress address
"明治通り, Shibuya, Tokyo"

> entry = { firstName: "Taro", lastName: "Suzuki", address: address } 
> showEntry entry
"Suzuki, Taro, 明治通り, Shibuya, Tokyo"

サンプルはそのままで動いた。

module  Data.AddressBook where

import Prelude

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

type Entry = { firstName :: String, lastName :: String, address :: Address }

type Address = { street :: String, city :: String, state :: String }

type AddressBook = List Entry

showEntry :: Entry -> String
showEntry entry = entry.lastName <> ", " <>
                  entry.firstName <> ", " <>
                  showAddress entry.address

showAddress :: Address -> String
showAddress address = address.street <> ", " <>
                      address.city <> ", " <>
                      address.state

emptyBook :: AddressBook
emptyBook = empty

insertEntry :: Entry -> AddressBook -> AddressBook
insertEntry = Cons

findEntry :: String -> String -> AddressBook -> Maybe Entry
findEntry firstName lastName = head <<< filter filterEntry
  where
    filterEntry :: Entry -> Boolean
    filterEntry entry = entry.firstName == firstName && entry.lastName == lastName

printEntry firstName lastName book
  = map showEntry (findEntry firstName lastName book)
> address = { street: "明治通り", city: "Shibuya", state: "Tokyo" }    
> entry = { firstName: "Taro", lastName: "Suzuki", address: address }  
> book1 = insertEntry entry emptyBook
> printEntry "Taro" "Suzuki" book1
(Just "Suzuki, Taro, 明治通り, Shibuya, Tokyo")

演習 1.

head は

List Entry -> Maybe Entry

filter は

(Entry -> Boolean) -> List Entry -> List Entry

AddressBook = List Entry なので読み替え可。

演習 2.

こんなんでいいのか?

module  Data.AddressBook where

import Prelude

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

type Entry = { firstName :: String, lastName :: String, address :: Address, phoneNumber :: String }

type Address = { street :: String, city :: String, state :: String }

type AddressBook = List Entry

showEntry :: Entry -> String
showEntry entry = entry.lastName <> ", " <>
                  entry.firstName <> ", " <>
                  showAddress entry.address <> ", " <>
                  entry.phoneNumber

showAddress :: Address -> String
showAddress address = address.street <> ", " <>
                      address.city <> ", " <>
                      address.state

emptyBook :: AddressBook
emptyBook = empty

insertEntry :: Entry -> AddressBook -> AddressBook
insertEntry = Cons

findEntry :: String -> String -> AddressBook -> Maybe Entry
findEntry firstName lastName = head <<< filter filterEntry
  where
    filterEntry :: Entry -> Boolean
    filterEntry entry = entry.firstName == firstName && entry.lastName == lastName

findEntryFromPhoneNumber :: String -> AddressBook -> Maybe Entry
findEntryFromPhoneNumber phoneNumber = head <<< filter filterEntry
  where
    filterEntry :: Entry -> Boolean
    filterEntry entry = entry.phoneNumber == phoneNumber


printEntry firstName lastName book
  = map showEntry (findEntry firstName lastName book)
> address = { street: "明治通り", city: "Shibuya", state: "Tokyo" }                            
> entry = { firstName: "Taro", lastName: "Suzuki", address: address, phoneNumber: "123-4567" } 
> book1 = insertEntry entry emptyBook                                                          
> findEntryFromPhoneNumber "123-4567" book1
(Just { address: { city: "Shibuya", state: "Tokyo", street: "明治通り" }, firstName: "Taro", lastName: "Suzuki", phoneNumber: "123-4567" })

> findEntryFromPhoneNumber "345-6789" book1 
Nothing

演習 3.

> import Data.List (null)                  
> :t null
forall (a :: Type). List a -> Boolean
import Data.List (List (..), filter, head, null)

isEntryExist :: String -> String -> AddressBook -> Boolean
isEntryExist firstName lastName = not <<< null <<< filter filterEntry
  where
    filterEntry :: Entry -> Boolean
    filterEntry entry = entry.firstName == firstName && entry.lastName == lastName

演習 4.

> import Data.List (nubBy)
> :t nubBy
forall (a :: Type). (a -> a -> Ordering) -> List a -> List a

できた。けどもっといい書き方ありそう。

removeDuplicates :: AddressBook -> AddressBook
removeDuplicates = nubBy compareEntry
  where
    compareEntry :: Entry -> Entry -> Ordering
    compareEntry e1 e2 =
      if lastCompare == EQ then
        firstCompare
      else
        lastCompare
        where
          lastCompare = compare e1.lastName e2.lastName
          firstCompare = compare e1.firstName e2.firstName



この記事が気に入ったらサポートをしてみませんか?