2015年6月29日月曜日

Pythonのsqlacodegenが便利です

SQLAlchemyのモデルクラスをDBから作ってくれる


PythonのORMでSQLAlchemyが好きな私ですが、最近のmigrationツールを使えなくなってきたお年寄りなので、

「テーブルから簡単にクラスを作ってくれるツールってないのか...」

と思いつつ、探していたら、sqlacodegenっていうのを見つけました、これSQLAlchemy用のORMクラスをデータベースから作成してくれるツールでシンプルでいけてる

インストール


まずはインストール、とりあえず適当にgentooのebuildを作っておきましたので、gentoo貴族はlaymanで入れて見てください。そのたのディストリビューションなかたはpipで入れて見てください。

karky7 ~ # layman -s karky7
...
...
karky7 ~ # emerge -pv sqlacodegen
...
Calculating dependencies... done!
[ebuild  N    ~] dev-python/inflect-0.2.5::karky7  PYTHON_TARGETS="python2_7 python3_3" 0 KiB
[ebuild  N    ~] dev-python/sqlacodegen-1.1.6::karky7  PYTHON_TARGETS="python2_7 python3_3 -python3_4" 0 KiB
..
..
karky7 ~ # emerge sqlacodegen

使ってみる


シェルからこんな感じで直接データベースを見にいかせるとモデルを全部吐いてくる
cuomo@karky7 ~ $ sqlacodegen mysql://root@localhost/SAMPLEDB
# coding: utf-8
from sqlalchemy import BigInteger, Column, DateTime, ForeignKey, Text
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base


Base = declarative_base()
metadata = Base.metadata


class BlogPost(Base):
    __tablename__ = 'BlogPost'

    id = Column(BigInteger, primary_key=True)
    title = Column(Text, nullable=False)
    authorId = Column(ForeignKey(u'Person.id'), nullable=False, index=True)

    Person = relationship(u'Person')


class Person(Base):
    __tablename__ = 'Person'

    id = Column(BigInteger, primary_key=True)
    name = Column(Text, nullable=False)
    age = Column(BigInteger)
    regdate = Column(DateTime)

その他のオプションはこんな感じ--tables [テーブル名]で関連するテーブルだけ吐いてきたり、いろいろできる。

cuomo@karky7 ~ $ sqlacodegen --help
usage: sqlacodegen [-h] [--version] [--schema SCHEMA] [--tables TABLES]
                   [--noviews] [--noindexes] [--noconstraints] [--nojoined]
                   [--noinflect] [--noclasses] [--outfile OUTFILE]
                   [url]

Generates SQLAlchemy model code from an existing database.

positional arguments:
  url                SQLAlchemy url to the database

optional arguments:
  -h, --help         show this help message and exit
  --version          print the version number and exit
  --schema SCHEMA    load tables from an alternate schema
  --tables TABLES    tables to process (comma-separated, default: all)
  --noviews          ignore views
  --noindexes        ignore indexes
  --noconstraints    ignore constraints
  --nojoined         don't autodetect joined table inheritance
  --noinflect        don't try to convert tables names to singular form
  --noclasses        don't generate classes, only tables
  --outfile OUTFILE  file to write output to (default: stdout)

最近、WAFへバンドルされているマイグレーションツールがいっぱいありますが、ちょっと使うには色々と覚える必要があるのでちょっと面倒くさい。
でもこのツールは、必要最低限でやりたいことがhelpを見るだけでできちゃうのが凄くいい。
SQLALchemy専用ですが、私はSQLAlchemy以外は使わないのでこれでいい、ちょっと注意点なんですが、テーブルのコメントなどにutf-8以外の文字コードを含んでいると、Unicodeエラーになってしまうので、その場合はALTER TABLEなどでコメントを削除するか、utf-8で入れ直すかしてみて下さい。

2015年6月23日火曜日

Persistentがまともに動きません

SelectOneManyとかもうないのか...


二日酔いが続く中、Database.Persist.Query.Join (SelectOneMany (..), selectOneMany)のあたりの関数がごっそりなくなっていて、嗚咽を模様した今日この頃です。

この辺の記事(「Yesod Web Framework SQL Join」)がそれっぽいようなことを書いてあるような気配がするのですが、英語も読む気力がないので、どなたか訳してくれないでしょうか...Orz

そんなことはいいとして、適当に書き換えてみました、データベースに入っているデータを単純に読み込むだけですが

データはこんな感じ
cuomo@karky7 ~ $ mysql -u root SAMPLEDB
Reading table information for completion of table and column names
...
...
mysql> SELECT * FROM Person;
+----+-------------------+------+
| id | name              | age  |
+----+-------------------+------+
| 11 | Kazuto Ando       |   40 |
| 12 | Yoshirou Dorumaki |   41 |
+----+-------------------+------+
2 rows in set (0.00 sec)

mysql> 
で、haskellのコード、Persistent MySQLを利用しています

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
import Database.Persist
import Database.Persist.MySQL
import Database.Persist.TH
import Data.Int
import Control.Monad.Logger (runNoLoggingT, MonadLogger)
import Control.Monad.IO.Class
import Control.Monad.Trans.Control (MonadBaseControl)

share [mkPersist sqlSettings] [persistUpperCase|
Person
    name String
    age Int Maybe
    deriving(Show)
BlogPost
    title String
    authorId PersonId
    deriving(Show)
|]

main :: IO ()
main = do
  person <- getPerson 11
  case person of
    Just p -> dispPerson (personName p) (personAge p)
    Nothing -> putStrLn "Nothing"

dispPerson :: String -> Maybe Int -> IO ()
dispPerson name (Just age) = putStrLn $ name ++ "\n" ++ show(age)
dispPerson name Nothing = putStrLn name

getPerson :: (MonadBaseControl IO m,
                        MonadIO m) => Int64 -> m (Maybe Person)
getPerson n = runNoLoggingT $ getConn $ runSqlConn $ do
   get (toSqlKey n)


getConn :: (MonadBaseControl IO m,
            MonadIO m,
            MonadLogger m) => (SqlBackend -> m a) -> m a
getConn = withMySQLConn getConnection

getConnection :: ConnectInfo
getConnection = ConnectInfo {
    connectHost = "localhost",
    connectPort = 3306,
    connectUser = "root",
    connectPassword = "",
    connectDatabase = "SAMPLEDB",
    connectOptions = [],
    connectPath = "",
    connectSSL = Nothing
}

そしたら、11番目の「かずと」を抜いてみる、最近、プロマネ的な仕事をこなしているっぽい、出世したらしい
*Main> :load "/home/cuomo/Code/yesod/Persistent/PersistMySQL.hs"
[1 of 1] Compiling Main       ( /home/cuomo/Code/yesod/Persistent/PersistMySQL.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
Kazuto Ando
40
*Main>
こんだけです、気持ちが悪いので止めておきます...


2015年6月22日月曜日

二日酔い

健康診断が控えた今日この頃、「二日酔い」という状態に陥りました。

しかし、今朝はいい天気です。

健康診断は、さらに高得点を叩き出すような気がします、皆さんも飲みすぎにはご注意下さい。




2015年6月13日土曜日

gentooでVirtualBoxやってみた

vmware playerからVirtualBoxに乗り換えてみた

昔ちょっと使っていたことはあったのですが、ネットワークまわりの設定が良く分からず放置していたのですが、

「VirtualBox、最近いいよ」

って付き合ってるかわいいJKにいわれたので、vmware playerから変えてみました。

インストぅール


まずは本体のインストール
cuomo@karky7 ~ $ uname -a
Linux karky7 3.14.2-gentoo #7 SMP Sat Feb 28 18:44:57 JST 2015 x86_64 Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz GenuineIntel GNU/Linux
カーネルやらはこんなバージョン、
karky7 ~ # emerge -pv app-emulation/virtualbox
...
[ebuild  N     ] app-emulation/virtualbox-modules-4.3.18::gentoo  USE="-pax_kernel" 525 KiB
[ebuild   R    ] app-emulation/virtualbox-4.3.18::gentoo  USE="additions alsa doc extensions java opengl pam pulseaudio python qt4 sdk vboxwebsrv -headless -vnc" PYTHON_TARGETS="python2_7" 5 KiB
...
karky7 ~ #

つづいて、その他の追加パッケージ、いらなかったらごめんなさい
karky7 ~ # emerge app-emulation/virtualbox-extpack-oracle \
app-emulation/virtualbox-guest-additions \
app-emulation/virtualbox-additions \
x11-drivers/xf86-video-virtualbox \
sys-apps/usermode-utilities \
net-misc/bridge-utils

そのままだと使えないので、ちょっと追加設定が必要、/etc/groupにVirtualBoxを利用するユーザーを含める
karky7 ~ # cat /etc/group
vboxusers:x:333:cuomo
vboxguest:x:777:cuomo
karky7 ~ # grpconv
karky7 ~ # systemctl enable virtualbox-guest-additions
Created symlink from /etc/systemd/system/multi-user.target.wants/virtualbox-guest-additions.service to /usr/lib64/systemd/system/virtualbox-guest-additions.service.
karky7 ~ # systemctl start virtualbox-guest-additions
karky7 ~ # 

一般ユーザーで起動、これで起動すればすべてよろしい。
cuomo@karky7 ~ $ VirtualBox


試しにSolaris11を入れてみる


ネットワーク構成はこんな感じでつくってみた



まずはネットワーク設定、Natネットワークを作成
このネットワークはゲストOSが外部へ通信出きるようにするためのネットワーク設定で、「Nat_global」という設定で作っておく。


続いてホストオンリーネットワークの設定、この設定はホストOS(gentoo)からゲストOSへSSHが出きるようにするためのいわゆるローカルネットワーク、どうもNatネットワークへSSHできないらしいので...



Solaris11.2のインストール

初期サーバー設定



メモリ設定、とりあえず2GB用意



ディスク設定



ディスクのタイプを選択、VirtualBox専用ファイルタイプ



ディスクは可変タイプ(sparse file)を指定

 

ファイルの場所とサイズ、めんどくせ



CPUの設定



ビデオメモリの設定、128MB与えてしまえ



インストール用SolarisのCDを仮想OSへ設定



NATネットワークを設定(仮想サーバーどもがグローバルへ出れるネットワーク)



ホストオンリーアダプタを設定(ホストOSがゲストOSにSSHするためのネットワーク)



そしたら、インストール開始、



インストールが終了するまで、ビールでも飲んでいてください...

ネットワーク設定

Solarisのネットワーク設定、まず、ホストオンリーネットワーク用デバイスがホストOSに作成されているか確認、gentoo上のネットワークデバイスの確認

karky7 ~ # ip addr
...
...
9: vboxnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet6 feff::8ff:ffff:feee:3/64 scope link 
       valid_lft forever preferred_lft forever
...

続いてSolaris(ゲストOS)のネットワーク設定、net0がNatネットワーク、net1がホストオンリーアダプタで設定されている

root@super-dev:~# netadm enable -p ncp DefaultFixed
root@super-dev:~# dladm show-phys
LINK              MEDIA                STATE      SPEED  DUPLEX    DEVICE
net1              Ethernet             unknown    1000   full      e1000g1
net0              Ethernet             unknown    1000   full      e1000g0
root@super-dev:~# ipadm create-ip net0
root@super-dev:~# ipadm create-ip net1
root@super-dev:~# ipadm create-addr -T static -a 192.168.254.2/24 net1/global1
root@super-dev:~# ipadm create-addr -T static -a 192.168.100.4/24 net0/global0
root@super-dev:~# echo '192.168.100.1' > /etc/defaultrouter 
root@super-dev:~# svccfg -s name-service/switch setprop config/host = 'astring: "files dns"'
root@super-dev:~#  svcadm refresh name-service/switch
root@super-dev:~# svccfg -s network/dns/client setprop config/nameserver = net_address: "(8.8.8.8 8.8.4.4)"
root@super-dev:~# svcadm refresh dns/client
root@super-dev:~# ipadm 
NAME              CLASS/TYPE STATE        UNDER      ADDR
lo0               loopback   ok           --         --
   lo0/v4         static     ok           --         127.0.0.1/8
   lo0/v6         static     ok           --         ::1/128
net0              ip         ok           --         --
   net0/global1   static     ok           --         192.168.100.4/24
net1              ip         ok           --         --
   net1/global0   static     ok           --         192.168.254.2/24

ホストオンリーアダプターのNICにSSHできるようになる、ちなみに192.168.100.1~3は予約らしく、設定すると外部と通信ができないので、4までずらしました。(よくわからない)

ここでsshできるか確認
cuomo@karky7 ~ $ ssh 192.168.254.2
Password: 
Last login: Sat Jun 13 16:17:56 2015 from 192.168.254.1
Oracle Corporation      SunOS 5.11      11.2    June 2014
cuomo@super-dev:~$ 
もしできないようだったら再起動するか、ホストオンリーアダプタを再設定してみるといいらしい(謎)

ゾーンをつくる


こんな感じで2つのNICをもったゾーンをつくる、色々やってはみたものの「net」設定で「ip-exclusive」な設定ですと、外部と通信できなくなってしまうので「ip-shared」で設定しました。まぁアプリケーションの動作環境としてはこの辺は関係ないのでいいとしています。「anet」だといくのかな?、どなたか教えてください....
root@super-dev:~# zonecfg -z chikubi
zonecfg:chikubi> export
create -b
set brand=solaris
set zonepath=/export/zones/chikubi
set autoboot=false
set autoshutdown=shutdown
set ip-type=shared
add net
set address=192.168.100.100/24
set configure-allowed-address=true
set physical=net0
end
add net
set address=192.168.254.100/24
set configure-allowed-address=true
set physical=net1
end
zonecfg:chikubi> 
そしたらインストールして、bootする

root@super-dev:~# zoneadm -z chikubi install
Progress being logged to /var/log/zones/zoneadm.20150613T073500Z.chikubi.install
       Image: Preparing at /export/zones/chikubi/root.

 Install Log: /system/volatile/install.6289/install_log
 AI Manifest: /tmp/manifest.xml.KWaiqm
  SC Profile: /usr/share/auto_install/sc_profiles/enable_sci.xml
    Zonename: chikubi
Installation: Starting ...

        Creating IPS image
開始 リンクされたイメージ: 1/1 完了
        Installing packages from:
            solaris
                origin:  http://192.168.254.3/
ダウンロード                 パッケージ  ファイル  転送 (MB)  速度
完了                               282/282   53274/53274  351.9/351.9  793k/s

フェーズ 項目
新しいアクションをインストールしています 71043/71043
パッケージ状態データベースを更新しています      完了 
パッケージキャッシュを更新しています         0/0 
イメージ状態を更新しています      完了 
スピード検索データベースを作成しています      完了 
パッケージキャッシュを更新しています         1/1 
Installation: Succeeded

        Note: Man pages can be obtained by installing pkg:/system/manual

 done.

        Done: Installation completed in 1103.209 seconds.


  Next Steps: Boot the zone, then log into the zone console (zlogin -C)

              to complete the configuration process.

Log saved in non-global zone as /export/zones/chikubi/root/var/log/zones/zoneadm.20150613T073500Z.chikubi.install
root@super-dev:~# zoneadm -z chikubi boot
root@super-dev:~# zlogin -C chikubi
...
...
これで、ゾーンが出来上がり、ゾーン内からグローバルへ、ホストOSからゾーンへのSSHなども出きるはず、あとは普通に使いうだけ。

ゲストOSへVirtualBox Addonのインストール


つづいて、コピペとか、ホストOSのディスクをゲストOSへ共有させたりとか、自動でウインドウをリサイズできる機能を追加設定する(vmware-toolsみたいな)、ゲストOSで仮想CDROMをマウントさせる


メニューから選択すると、ゲストOSにCDROMがマウントされる


そうしましたら、以下のコマンドをrootで実行、Solarisですとグローバルゾーンで実行します

root@super-dev:~# cd /media/VBOXADDITIONS_4.3.18_96516/
root@super-dev:/media/VBOXADDITIONS_4.3.18_96516# pkgadd -G -d ./VBoxSolarisAdditions.pkg

The following packages are available:
  1  SUNWvboxguest     Oracle VM VirtualBox Guest Additions
                       (i386) 4.3.18,REV=r96516.2014.10.10.21.35

Select package(s) you wish to process (or 'all' to process
all packages). (default: all) [?,??,q]: 

Processing package instance <SUNWvboxguest> from </media/VBOXADDITIONS_4.3.18_96516/VBoxSolarisAdditions.pkg>

Oracle VM VirtualBox Guest Additions(i386) 4.3.18,REV=r96516.2014.10.10.21.35
Oracle Corporation
Using </> as the package base directory.
## Processing package information.
## Processing system information.
## Verifying package dependencies.
## Verifying disk space requirements.
## Checking for conflicts with packages already installed.
## Checking for setuid/setgid programs.

This package contains scripts which will be executed with super-user
permission during the process of installing this package.

Do you want to continue with the installation of <SUNWvboxguest> [y,n,?] y
...
...
...
Configuring VirtualBox guest kernel module...
VirtualBox guest kernel module loaded.
VirtualBox pointer integration module loaded.
Creating links...
Installing video driver for X.Org 1.14.5...
Configuring client...
Installing 64-bit shared folders module...
Installing 32-bit shared folders module...
Configuring services (this might take a while)...
Enabling services...
Updating boot archive...
Done.
Please re-login to activate the X11 guest additions.
If you have just un-installed the previous guest additions a REBOOT is required.

Installation of <SUNWvboxguest> was successful.
root@super-dev:/media/VBOXADDITIONS_4.3.18_96516# 

そしたら、rebootしましょう

再起動後、前より使い勝手が良くなっているはず、Addonの機能を有効にすればつかえるようになります。


この辺はLinuxでも同じように設定できます、vmware playerよりは細かいネットワーク設定ができるなかっていう感じがします。ビデオキャプチャーとかちょっとした機能があるところもいいですかね。

Macと仮想環境を共有出きるところもいいですね、ちなみに「JKと付き合っている」ことは内緒にしておいて下さい。


 


2015年6月6日土曜日

haskellでMeCab(形態素解析)をやってみた

お酒にやられた体に必要なものは、メカブです...

まずはインストール


超有名な形態素解析エンジンのMeCabさんをインストゥールする、まずは本体と辞書
karky7 ~ # emerge -pv app-text/mecab

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N     ] app-text/mecab-0.996::gentoo  USE="unicode -static-libs" 1,366 KiB
[ebuild  N     ] app-dicts/mecab-ipadic-2.7.0.20070801::gentoo  USE="unicode" 11,922 KiB

Total: 2 packages (2 new), Size of downloads: 13,288 KiB

 * IMPORTANT: 34 news items need reading for repository 'gentoo'.
 * Use eselect news read to view new items.

karky7 ~ # 
さすがgentoo一発ですね、つづいてMeCab Haskell
karky7 ~ # emerge -pv dev-haskell/mecab

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild   R   ~] dev-haskell/mecab-0.4.0-r1:0/0.4.0::haskell  USE="doc hoogle hscolour profile" 0 KiB

Total: 1 package (1 reinstall), Size of downloads: 0 KiB

 * IMPORTANT: 34 news items need reading for repository 'gentoo'.
 * Use eselect news read to view new items.

karky7 ~ # 

Haskellで動かしてみる


いっぱいオプションがあるのですが、わからないのでつかわない
{-# LANGUAGE OverloadedStrings #-}
import Text.MeCab

main :: IO()
main = do
  let str = [ "和人が和人でシャープA", "カズトも荒んでる",
              "ヨシロウトカズトガナイスガイ", "ヨシロウとカズトがナイスガイ" ]
  mapM_ putStr =<< mapM wakati str

wakati :: MeCabString s => s -> IO s
wakati str = new2 "-O wakati -l2" >>= parse' str

parse' :: MeCabString s => s -> MeCab -> IO s
parse' = flip parse
うごかしてみると、
~/Code/haskell/MeCab $ runghc MeCab5.hs
和人 が 和人 で シャープ A
カズト も 荒ん でる
ヨシロウトカズトガナイスガイ
ヨシロウ と カズト が ナイスガイ
~/Code/haskell/MeCab 
ヨシロウトカズトガカタカナでつながっていると分けられないようです、MeCabも分けられない強力な繋がりをもっているのでしょう...



2015年6月1日月曜日

HaskellのgetStdRandom関数

getStdRandomなにこれ?


手続き型言語の乱数生成ロジックになれた腐れ脳では、Haskellの乱数生成流儀についていくのがオックウになった今日この頃ではありますが、暇なのでSystem.Randomを弄って見ました。

乱数系の関数はSystem.Randomモジュールにあるのですがその中でgetStdRondom関数というのがあってこれがちょっと分かりにくかった。

その関数というのがこんな感じ、
Prelude> :m +System.Random
Prelude System.Random> :t getStdRandom
getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
ちょっと使ってみる
Prelude System.Random> getStdRandom $ \g -> (random g, g)
(6296841432639150751,794839904 2103410263)
Prelude System.Random> getStdRandom $ \g -> (random g, g)
(6296841432639150751,794839904 2103410263)
Prelude System.Random>
結果は同じ、同じ乱数ジェネレータで乱数を生成しているため、同じ乱数しか返ってこない、これではこまる
getStdRandom関数は「StdGenを引数にとってタブル(値,乱数ジェネレータ)を返す関数」を引数にとるのですが、この時乱数ジェネレータを新しいものにするとそれを書き換えてくれるという便利な関数で、いたれりつくせりでちょっと分かりにくい。
で、どうなってるのか気になったのでソースコードをみてみた
...
theStdGen :: IORef StdGen
...
...
getStdRandom :: (StdGen -> (a,StdGen)) -> IO a
getStdRandom f = atomicModifyIORef theStdGen (swap . f)
  where swap (v,g) = (g,v)
theStdGenはIORefにくるまった乱数ジェネレータで、atomicModifyIORef関数は
Prelude System.Random> :m Data.IORef
Prelude Data.IORef> :t atomicModifyIORef
atomicModifyIORef :: IORef a -> (a -> (a, b)) -> IO b
Prelude Data.IORef> 
これは、「IORef aな変数とaをとって(更新後の値,戻値にしたい値)を返す関数」を引数にとるという頭が腐りそうになる関数らしく、IORefから乱数ジェネレータをはがして、それを第2引数の関数への入力へつかってその関数が返してきた、値と新しい乱数ジェネレータをもらって、値はそのまま返して、ついでに新乱数ジェネレータで旧乱数ジェネレータを更新する(であってるかどうか分かりませんが...)

長い...

第2引数のタプルは(値,乱数ジェネレータ)になっているのでswapしてる、なるほどぉー。
それが分かれば、こうやって使うのも自然に分かる
Prelude Data.IORef System.Random> :t randomR
randomR :: (Random a, RandomGen g) => (a, a) -> g -> (a, g)
Prelude Data.IORef System.Random> :t randomR (1, 100)
randomR (1, 100) :: (Random a, RandomGen g, Num a) => g -> (a, g)
Prelude Data.IORef System.Random> 
Prelude Data.IORef System.Random> getStdRandom $ randomR (1, 100)
95
この関数は範囲指定の乱数を生成してくれて、第1引数に範囲をしてすればgetStdRandomの引数に使える関数になる、ちなみにrandomRは新しい乱数ジェネレータを返してくれる。

リストで乱数が欲しいなら、こうして
Prelude> :m +System.Random
Prelude System.Random> :m +Control.Arrow
Prelude System.Random Control.Arrow> :t ((take 10) . fst . first randoms . split)
((take 10) . fst . first randoms . split)
  :: (Random a, RandomGen b) => b -> [a]
Prelude System.Random Control.Arrow> let gen = mkStdGen 10
Prelude System.Random Control.Arrow> :t ((take 10) . fst . first randoms . split) 
((take 10) . fst . first randoms . split)
  :: (Random a, RandomGen b) => b -> [a]
Prelude System.Random Control.Arrow> ((take 10) . fst . first randoms . split) gen
[429082465013243227,-2464015050900774578,7201080910402330150,-3257845164067810313,-4921980529382864518,1852978159347469817,8762143554925919814,-368579347710764073,-3030540427141715674,5472412\
645992684729]
Prelude System.Random Control.Arrow>
splitで乱数ジェネレータを更新しているので実行する度に違う乱数がちゃんと返ってくる、乱数生成にしても関数プログラミングでやるとまったく違ったアプローチになるのですね、やっぱ知っとかないとね。

とにかく、Haskellはたのしい。