結城浩のHaskell日記 RSSフィード

2006-06-02

:browse :browse - 結城浩のHaskell日記 を含むブックマーク

GHCiで:browseも便利ですね。モジュールをブラウズする。

Prelude> :b Char
data Char =
ord :: Char -> Int
chr :: Int -> Char
type String = [Char]
intToDigit :: Int -> Char
showLitChar :: Char -> String -> String
digitToInt :: Char -> Int
lexLitChar :: String -> [(String, String)]
readLitChar :: String -> [(Char, String)]
isAlpha :: Char -> Bool
isAlphaNum :: Char -> Bool
isAscii :: Char -> Bool
isControl :: Char -> Bool
isDigit :: Char -> Bool
isHexDigit :: Char -> Bool
isLatin1 :: Char -> Bool
isLower :: Char -> Bool
isOctDigit :: Char -> Bool
isPrint :: Char -> Bool
isSpace :: Char -> Bool
isUpper :: Char -> Bool
toLower :: Char -> Char
toUpper :: Char -> Char

error関数 error関数 - 結城浩のHaskell日記 を含むブックマーク

errorでエラーを表せるようです。

Prelude> :info error
-- error is a variable
error :: forall a :: ?. [Char] -> a
Prelude> error "Hello"
*** Exception: Hello

これで先日悩んでいたエラーが出せる。

myhead :: [a] -> a
myhead [] = error "myhead: []"
myhead (x:xs) = x

実行結果です。

*Main> myhead [1,2,3]
1
*Main> myhead[]
*** Exception: myhead: []

練習の題材 / 単に定義するだけではなく 練習の題材 / 単に定義するだけではなく - 結城浩のHaskell日記 を含むブックマーク

nobsunから、

list上の再帰関数は殆どの場合、Preludeにある高階関数を使って書けます。練習してみると楽しいですよ。

という題材をいただきました。忘れないようにメモ。

そうか…作りたい関数があったとして、

  • 反復的(iterative)に作る(これってaccumulativeに作るのと同じかな)
  • 再帰的(recursive)に作る
  • 高階関数を使って作る

などを意識するのは大事ですね。Schemeだとさらに、

  • Continuation Passing Styleで

などもありえますね。他には、

  • evalを使って
  • reflectionを使って(evalとちょっと似ている)

など、いろいろ考えられそうです。

単に定義するだけではなく、いま自分がどういうスタイルで書いているかを意識するのは重要かも。少なくとも楽しそうだ。

=>と-> =>と-> - 結城浩のHaskell日記 を含むブックマーク

Haskellに関するだれかの日記で => と -> を混同していると思われる記事があって「あ、コメントしなくちゃ」と思っていたんだけれど、再発見できない。あれはどなたの日記だったでしょうか…。

ええと、確か、

(Num t) => t

に関する話題だったと思います。=>って関数の->とは違いますよね?

追記:コメントで教えていただきました。トーフサロンのcarverさんのところでした。

追記:=>と->の勘違いではなく、 :: に関する勘違いだったようです。こういうふうに勘違いしたのかな、と勘違いしていました。すみませんです (^_^;;

if-then-else if-then-else - 結城浩のHaskell日記 を含むブックマーク

ifでthenかelseのいずれかだけが評価されることの確認。

debugPrintの型 String -> IO () は、ghciで:type putStrLnの型を調べて見よう見まねです。

debugPrint :: String -> IO ()
debugPrint msg = putStrLn ("DEBUG: " ++ msg)

ifTest :: Bool -> IO ()
ifTest b = if b then debugPrint "then"
                else debugPrint "else"

実行結果です。

> ghci a.hs
...
*Main> ifTest True
DEBUG: then
*Main> ifTest False
DEBUG: else
*Main> ifTest (0 == 0)
DEBUG: then
*Main> ifTest (0 == 1)
DEBUG: else
*Main> ifTest (isUpper 'A')

<interactive>:1: Variable not in scope: `isUpper'
*Main> ifTest (Char.isUpper 'A')
DEBUG: then
*Main>

次はp.120から。

偶数と奇数の個数比較 偶数と奇数の個数比較 - 結城浩のHaskell日記 を含むブックマーク

'()はnullに触発され「整数のリストを与えられて、偶数が多ければTrue, それ以外はFalseになる関数evenGtOdd」を作ります。

evenGtOdd :: [Integer] -> Bool
evenGtOdd x = iterate x 0 0
  where
    iterate [] e o = e > o
    iterate (n:ns) e o | isEven n  = iterate ns (e + 1) (o + 0)
                       | otherwise = iterate ns (e + 0) (o + 1)
    isEven n = n `mod` 2 == 0

実行結果です。

*Main> evenGtOdd [1..5]
False
*Main> evenGtOdd [1..6]
False
*Main> evenGtOdd [1,2,3,4,6]
True
*Main> evenGtOdd []
False
*Main> evenGtOdd [2]
True

できたできた。何だか頭が体操しているみたいですがすがしい。

追記:nobsunから、even, iterateがPreludeにあることを教えていただきました。いつもありがとうございます。ではさっそく修正。

  • 自作のisEvenをやめて、Prelude.evenを使った。
  • iterateをやめて、代わりにcountEvenOddという局所関数を作った。
evenGtOdd :: [Integer] -> Bool
evenGtOdd ns = countEvenOdd ns 0 0
  where
    countEvenOdd [] e o = e > o
    countEvenOdd (n:ns) e o | even n    = countEvenOdd ns (e+1) (o+0)
                            | otherwise = countEvenOdd ns (e+0) (o+1)

Haskellの遅延評価 Haskellの遅延評価 - 結城浩のHaskell日記 を含むブックマーク

ふつける」第二部に入りました。

Haskellの遅延評価(p.104)。

  • 最外簡約
  • グラフ簡約

nobsunnobsun2006/06/02 09:23iterateはPreludeにある関数名に使われているので
局所名であっても、避けたほうがよいかも。

nobsunnobsun2006/06/02 09:25evenというPrelude関数があります。

IO ()IO ()2006/06/02 10:37=>と-> 「トーフサロン」ですね。

YukoYuko2012/05/03 00:21Thanks for the great info dog I owe you biggtiy.

ijjuqlpcijjuqlpc2012/05/03 11:18XUNcWZ <a href="http://yaiunxzffsja.com/">yaiunxzffsja</a>

トラックバック - http://haskell.g.hatena.ne.jp/hyuki/20060602