のびのびなHaskell日記

2006-07-17

パターンマッチ

フツケル 168頁

変数パターンの定義をフツケル170頁より引用します。

id :: a -> a
id x = x
仮引数の「x」が変数パターンです。
変数パターンはどんな値に対してもマッチし、その値に変数を束縛します。
 --変数パターンのサンプルコード
hoge x = print x
main = do hoge 1
          hoge 10

最初引用した変数パターンの説明に出てくる、「その値に変数を束縛します」を以下のように勘違いしていました。

hoge xの変数xを値に束縛するということは、hoge 10はhoge xにマッチするから、xを10に束縛する。Haskellは再代入は出来ない。

従ってhogeメソッドを抜けてもxの値は10であるはず(?)ということで以下のようなコードを書いていました。結果は「Not in scope: `x'」とエラーが表示されて実行出来ません。

xは仮引数ですから、メソッドを抜けたら値を消失するからエラーが出て当たり前と言えば当たり前なのですが、束縛しますと書いてあったのでメソッドを抜けても10にxが束縛されているのかと思ってしまいました(^_^;)

hoge x = x
main = do print $ hoge 1
          print x
トラックバック - http://haskell.g.hatena.ne.jp/NobiNobiKota/20060717

2006-07-16

昇順ソートと降順ソート

import List

list = [2,9,8,49,299,34,99,103,3]

main = do putStr "Orginal "
          print list
          putStr "ASC "
          print $ sortBy(\x y -> compare x y )list -- 昇順ソート
          putStr "DESC "
          print $ sortBy(\x y -> compare y x )list -- 降順ソート
  • 実行結果
D:\Development\PracticeHaskell\work20060715>runghc sample05.hs
Orginal [2,9,8,49,299,34,99,103,3]
ASC [2,3,8,9,34,49,99,103,299]
DESC [299,103,99,49,34,9,8,3,2]

6文字以上の文字列はどれとどれ?

リストの中に入っている文字列で、文字列の長さが6文字以上のものをリストに入れて返してもらう処理を書いてみました。

import List

list = ["Oasis","THE CRANBERRIES","Keane","Maroon 5","DEF LEPPARD"]

main = print $ filter isGreaterThan6Characters list

isGreaterThan6Characters x = (length x) >= 6 
import List

list = ["Oasis","THE CRANBERRIES","Keane","Maroon 5","DEF LEPPARD"]

main = print $ filter (\x -> (length x) >= 6) list
import List

list = ["Oasis","THE CRANBERRIES","Keane","Maroon 5","DEF LEPPARD"]

main = print $ filter ( ( >=6 ) . length) list
["THE CRANBERRIES","Maroon 5","DEF LEPPARD"]

__2006/07/18 02:26filter (not . null . drop 5)
無限リストでもOK

NobiNobiKotaNobiNobiKota2006/07/18 03:48filter (not . null . drop 5) ←これは思いつきませんでした(^_^;)

トラックバック - http://haskell.g.hatena.ne.jp/NobiNobiKota/20060716

2006-07-10

「フツケル」131頁から134の学習

整数

  • Int型とInteger型

Haskell整数型にはInt型とInteger型の二種類ある。

文脈によって同じ5でもInt型にもなるし、Integer型にもなる。また浮動小数点型にもなる。文脈が数値リテラルの型を決める。

文脈によらず数値リテラルの型を限定するには以下のように宣言する。

    • x = (2 :: Int)

この場合は数値リテラルの2がInt型と宣言され、Int型の2を変数xに束縛しています。

    • y = (3 :: Integer)

この場合は数値リテラルの3はInteger型と宣言され、Integer型の3を変数yに束縛しています。

  • 型の異なる同士の演算

型が異なる同士の演算を行うには、明示的に型を変換する必要がある。

 -- xの型はInt型
x = (15 :: Int)
 -- yの型はInteger型
y = (10 :: Integer)

 -- xとyの型は異なるので、このままだと演算は出来ない。
 -- x又はyのどちらかを一方の型に変換することによって演算が可能になる。
main = do print $ (toInteger x) + y     -- xの型をInteger型に変換
          print $ x + (fromInteger y)   -- yの型をInt型に変換
          print $ (fromIntegral x) + y  -- xの型をInteger型に変換
          print $ x + (fromIntegral y)  -- yの型をInt型に変換
  • toInteger x、fromInteger x及びfromIntegral xの定義
    • toInteger x

Int型の値xをInteger型に変換します。

    • fromInteger x

Integer型の値xを数値型に変換します。但し返り値の型は文脈で決まります。

整数型ではなく数値型に変換するという点に注目。演算相手がFloat型だとfromInteger xはFloat型を返すということかな?(未確認)

    • fromIntegral x

Int型又はInteger型の値xを数値型に変換します。但し返り値の型は文脈で決まります。この関数もfromInteger同様に整数型ではなく数値型に変換するという点に注目。自分の演算相手がDouble型であれば、Double型に変換して返してくれるということかな?(未確認)

トラックバック - http://haskell.g.hatena.ne.jp/NobiNobiKota/20060710

2006-07-06

真偽値

「フツケル」129頁から130頁のまとめ

  • not関数
    • not :: Bool -> Bool
    • not xはxがTrueのときFalseを、xがFalseのときはTrueを返す関数です。
  • (&&)関数
    • (&&) Bool -> Bool -> Bool
    • x && yはxとyがともにTrueのときTrueを返します。それ以外のときはFalseを返します。
  • (||)関数
    • (||) :: Bool -> Bool -> Bool
    • x || yはxとyのいずれかがTrueのときTrueを返します。
 -- ファイル名:sample_bool.hs
main = do print $ ("not (1 == 1)",not (1 == 1))
          print $ ("not (1 == 3)",not (1 == 3))
          print $ ("(10 == 10) && (20 == 20)",(10 == 10) && (20 == 20))
          print $ ("(62 == 30) && (20 == 20)",(62 == 30) && (20 == 20))
          print $ ("(30 == 30) && (20 == 10)",(30 == 30) && (20 == 10))
          print $ ("(5  == 2 ) && (3  ==  1)",(5  == 2 ) && (3  ==  1))
          print $ ("('a' == 'a') || ('b' == 'b')",('a' == 'a') || ('b' == 'b'))
          print $ ("('a' == 'a') || ('b' == 'c')",('a' == 'a') || ('b' == 'c'))
          print $ ("('a' == 'd') || ('b' == 'b')",('a' == 'd') || ('b' == 'b'))
          print $ ("('p' == 'q') || ('r' == 's')",('p' == 'q') || ('r' == 's'))
d:\Development\PracticeHaskell>runghc sample_bool.hs
("not (1 == 1)",False)
("not (1 == 3)",True)
("(10 == 10) && (20 == 20)",True)
("(62 == 30) && (20 == 20)",False)
("(30 == 30) && (20 == 10)",False)
("(5  == 2 ) && (3  ==  1)",False)
("('a' == 'a') || ('b' == 'b')",True)
("('a' == 'a') || ('b' == 'c')",True)
("('a' == 'd') || ('b' == 'b')",True)
("('p' == 'q') || ('r' == 's')",False)
トラックバック - http://haskell.g.hatena.ne.jp/NobiNobiKota/20060706

2006-07-05モジュール

「フツケル」の250頁

 --ファイル名:greeting.hs
module Greeting where
hello = putStr "Hello,World!"
 --ファイル名:greeting_client.hs
import Greeting
main = hello
  • greeting_client.hsを実行してみました。
D:\Development\PracticeHaskell\work20060704>runghc greeting_client.hs
Hello,World!
  • 次にgreeting_client.hsをコンパイルしてみましたが、エラーが出ました。今のところ原因不明(メモ)
D:\Development\PracticeHaskell\work20060704>ghc greeting.hs -o greeting
C:/ghc/ghc-6.4.2/libHSrts.a(Main.o)(.text+0x1d):Main.c: undefined reference to `
__stginit_ZCMain'
C:/ghc/ghc-6.4.2/libHSrts.a(Main.o)(.text+0x43):Main.c: undefined reference to `
ZCMain_main_closure'
collect2: ld returned 1 exit status
 --Greetingモジュールの中身そのままで、ファイル名をgreeting_mod.hsに変更
module Greeting where
hello = putStr "Hello,World!"
 --greeting_client.hsの実行結果
D:\Development\PracticeHaskell\work20060704>runghc greeting_client.hs
Could not find module `Greeting':
  use -v to see a list of the files searched for
  (imported from greeting_client.hs)

Greetingモジュールをロードするために、Greetingというファイルを探したけど見つからなかったということですね。モジュール名とファイル名は一致していないといけないのかも

  • ファイル名をgreeting.hsに戻して、モジュール名をGreetingからGreetingModに変更してみてgreeting_client.hsを実行してみました。
 --ファイル名:greeting.hs
module GreetingMod where
hello = putStr "Hello,World!"
 --greeting_client.hsを実行した結果
D:\Development\PracticeHaskell\work20060704>runghc greeting_client.hs
./Greeting.hs: file name does not match module name `GreetingMod'

ファイル名がモジュール名と一致していないと分かりやすいエラーが表示されました。やはりファイル名とモジュール名は一致していないといけないということでしょうか(^_^;)

トラックバック - http://haskell.g.hatena.ne.jp/NobiNobiKota/20060705