1. 繰り返しのある数値を生成したい
Haskell で、与えられた数値を、繰り返す関数を定義したい。
例えば、1234567890 を与えたら、
`1234567890123456790123…’
のように、数値を繰り返した結果を得たい。
2. はじめに思い付いた面倒な方法
はじめに思い付いた方法は、
- 0 ~ 9 のリストを指定した回数だけ複製したものを連結して、
- Integer 型に変換する makeNum 関数を作成すること。
makeNum 関数の中では、次のようなリストが渡されたら、
- [0,1,2,3,4,5]
同じ長さの、 0 からはじまって 1 ずつ増加する数列を作り、
- [0,1,2,3,4,5] → 反転させ [5,4,3,2,1,0]
zip でくっつける。
- [(0,5), (1,4), (2,3), (3,2), (4,1), (5,0)]
それぞれの要素を (a,b) とすると、a*10^b したものを foldl1 で足し合わせるという方法。
makeNum :: [Integer] -> Integer makeNum xs = foldl1 (+) [a*10^b | (a,b) <- zip xs $ reverse [0..(length xs)-1]] main = do print $ makeNum $ concat $ replicate 3 [0..9]
この方法は、わかりずらい… (@_@;)
3. Python で実装するには
Python だったら、どう定義するか考えた。
def makeNum(L): return long("".join(str(x) for x in L)) print makeNum(range(0,10) * 3)
数値のリストを渡したら、空文字で join して long() で数値へ変換。
4. Haskell の Read クラスを使う
上記のPython で書いたように、
文字列から数値に変換する
ことができたら、はじめに考えた方法よりも、簡単に実装できそう。
「あれ?でもそんな関数ってあったかな?」
と思い検索してみると、Re: string to Integer に、
Turning a string into an integer is easy with the Prelude function 'read': n :: Integer n = read "-34232"
あらら、Prelude にあったとは気がついてなかった… ^^;
Prelude にある
を読むと、文字列 <ー> 型 の変換をするため方法が解説されている。
これによると、
Show <-> Read
- 文字列への変換のための Show クラス
- 文字列からの変換のための Read クラス
Showクラス については、以下を参照。
read メソッドの型
read 関数を見ると、最後の型が、型変数 a となっており、Read クラスの制約が付いている。
これは、
- Haskell の数値 – Int は型で Num は型クラス の maxBound 関数
で見た形と同じ。
read メソッドを使えば、
print $ (read $ concatMap show $ concat $ replicate 3 [0..9] :: Integer)
5. cycle 関数でリストを繰り返す
`1234567890123456790123…’ を延々と繰り返される無限リストのように見立てる。そこから、一部を取り出す関数を考える。与えられた引数を延々と繰り返す infstr 関数を定義するなら、
infstr :: String -> String infstr cs = cs ++ infstr(cs) main = do print $ (read $ take 30 $ infstr "1234567890" :: Integer)
しかし、こんな基本的な関数、どこかに定義してあるのではないかと思い Prelude を探すと、
repeat があった。しかし、これは対象がリストではなない。
repeat 関数の近くに、cycle 関数があった。
cycle :: [a] -> [a]
これを使えば、
print $ (read $ take 30 $ cycle "1234567890" :: Integer)
と極めてシンプルに定義できる。
一体全体、最初何を書いていたのやら。(o_ _)o~†
cycle 関数の定義で気になったこと
ところで、cycle の実装を見ると、
cycle :: [a] -> [a] cycle [] = error "Prelude.cycle: empty list" cycle xs = xs' where xs' = xs ++ xs'
xs’ = where … と書くのは、なにか理由があるのかな ?
1コメント:
Exceptional post however , I was wondering if you could write a litte more on this subject?
I'd be very thankful if you could elaborate
a little bit further. Thank you!
My webpage: search engine
コメントを投稿