2025年4月7日月曜日

myPlayer


-- pipe.hs
import System.Process
import System.Environment
main :: IO () 
a:_ <- getArgs
    (_, Just so, _, _)  <- createProcess (proc "runghc" ["randomList.hs",a]) { std_out = CreatePipe } 
    _ <- createProcess (proc "/home/i/myPlayer/viewer" []) { std_in = UseHandle so }
    return ()

-- randomList.hs
import System.Random
import System.Process
import System.Posix.Time (epochTime)
import System.Environment
import System.Directory
import System.FilePath.Posix
imnum = 10
lines' = return . lines
randomize :: [FilePath] -> IO [FilePath]
randomize lst = do
    let c = length lst
    r <- fromEnum <$> epochTime >>= (\x -> return (randomRs (0, (c-1)) (mkStdGen x) ))
    return [lst !! x|x <- take imnum r]
dirFilePairs :: [FilePath] -> IO [(FilePath,FilePath)]
dirFilePairs lst = return [(takeDirectory x,x) | x <- lst]
fileFilePairs :: [(FilePath,FilePath)] -> IO [(FilePath,FilePath)]
fileFilePairs = mapM (\(a,b) -> do{aa <- getAA a; return (aa,b)})
    where
        getAA p = do
            fs <- listDirectory p >>= filtFile ".jpg"
            if fs == [] then return "cd.jpg"
                        else return $ p ++ ['/'] ++ head(fs)
        filtFile ex = return . filter (\x -> takeExtension x == ex)
main = do
    fs <- getArgs >>= \(a:_) -> readFile a
    lines' fs >>= randomize >>= dirFilePairs >>= fileFilePairs >>= print
                                                                                                                      1,1          全て

-- viewer.hs
import Graphics.UI.Gtk
import System.Process
import MyButton
iSize = 100
getAps :: IO [(FilePath,FilePath)]
getAps = getContents >>= return . read
func1 f = createProcess (proc "audacious" [f]) >> return ()
main = do
    aps <- getAps
    initGUI
    w <-  windowNew
    set w [windowWindowPosition := WinPosNone,
            windowDefaultWidth := 400, windowDefaultHeight := 900]
    vb <- vBoxNew False 0
    sw <- scrolledWindowNew Nothing Nothing
    scrolledWindowAddWithViewport sw vb
    containerAdd w sw
    bs <- mapM (\(a,b) -> newImgButton iSize (a,b) func1) aps
    mapM (containerAdd vb) bs
    widgetShowAll w
    w `on` unrealize $ mainQuit
    mainGUI
~            
-- MyButton.hs
module MyButton where
import Graphics.UI.Gtk
newImgButton size (f,f') func = do
    p <- pixbufNewFromFileAtSize f size size
    i <- imageNewFromPixbuf p
    b <- buttonNew
    set b [buttonImage := i]
    l <- labelNew $ Just $ drop 12 f'
    set l [labelWrap := True]
    hb <- hBoxNew False 0
    containerAdd hb b
    containerAdd hb l
    b `on` buttonActivated $ func f'
    return hb
      

2020年5月23日土曜日

Haskell Process

Haskellの System.Processは便利ですが、問題もあります。

単一スレッドでの逐次処理を保証していない。(想像です。)

次のようなスクリプトを書いてみた。

--a.hs
main = print [1..10]

--t.hs
import System.Process
loop x = createProcess (proc "runghc" ["a.hs"]) >> return ()
main = mapM_ loop [1..100]

実行結果。

$ runghc t.hs
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,[1,2,3,4,5,6,7,8,9,1[1,2,3,4,5,6,7,8,9,10]
5,6,7,8,9,10]
0]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,[1,2,3,4,5,6,7,8,9,10]
,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10[1,2,3,4[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4[1,2,3,4,5,6,7,8,9,10]
i@i:~/haskell$ [1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,,[1,2,3,4,5,6,7,8,9,10]
5,6,7,8,9,10]
]
[1,2,3,4,5,6,7,8,9,10]
,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3[1,2,3,4,5,6,7,8,9,10,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
,[1,2,3,4,5,6,7,8,9,10]
5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
]
[1,2,3,4,5,6,[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[[1,2,3,4,5,6,7,8,9,10]
1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,1[1,2,3,4,5,6,7,8,9,10]
7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
0[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
]
[1,2,3,4,5,6,7,8,9,10]
[[1,2,3,4,5,6,7,8,9,10]
1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8[1,2,3,4[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,,,5,6,[7,8,19,1,02]
,3,4,5,6,7,8,9,10]
9,10]
[1,2,3,4,5,6,7,8,9,10]
5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]

[1..10]のリストを書き終える前に次のリストを書き始めている。
100回のLoop の途中で t.hs スクリプトを終了している。

深い意味は僕には不明ですが、実用プログラムで使う場合には注意が必要なのでは・・・。

2019年2月13日水曜日

セル・オートマトン

ソースコードは下記アドレス


1次元のセル・オートマトンにルール30を適用して得た画像。

一部Repaを使ってみました。







以下のインストール が必要。

$ cabal update -v
$ cabal install repa -v
$ cabal -v install repa-io
$ cabal install parallel -v

コンパイルは

$ ghc -O2 -threaded -rtsopts --make -XFlexibleContexts -eventlog cellA.hs

作成された実行ファイルを実行します。

$ ./cellA 110 +RTS -N2 -l

ルールはコマンドライン引数で与えます。

eventlog が作成されます。

$ threadscope cellA.eventlog

 一応2コアで動いています。



ルール110の実行例。

$ display a.bmp

ルール45
ルール225

2018年12月3日月曜日

Github リポジトリにファイルを追加

Githubのリポジトリにファイルをグラフィカルに追加する方法。 記事が少なくなかなかわからなかった。

赤丸の位置にファイルブラウザーから追加したいファイル(複数可)をドラッグすればよい。
内容の更新も同様。

update files というボタンを押してもよい。

2018年11月2日金曜日

Module ‘System.Cmd’ is deprecated

--b.hs 
import System.Cmd 
main = rawSystem "ls" ["-lh"] 

$ runghc b.hs
b.hs:1:1: Warning:
     Module ‘System.Cmd’ is deprecated: Use "System.Process" instead


import  System.Process 
main = createProcess (proc"ls" ["-lh"])

2018年6月21日木曜日

複素数

Pythonは複素数を直接書くことができます。

Python 2.7.12 (default, Dec  4 2017, 14:50:18)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a=0+1j
>>> a
1j

実数部が0のとき省略できます。

>>> a=1j
>>> a
1j

虚数部が0のときこれも省略できます。

>>> b=1
>>> b
1

これはただの実数ですが複素数と組み合わせるとちゃんと複素数の計算をしてくれます。

>>> a-b
(-1+1j)

複素数は距離の計算をとても楽にしてくれます。

a,b 2点間の距離は差をとって絶対値を計算すればよい。

>>> d=abs(a-b)
>>> d
1.4142135623730951

これは√2です。
これをbに代入します。

>>> b=d
>>> b
1.4142135623730951
>>> d=abs(a-b)
>>> d
1.7320508075688774

これは√3です。
このように計算結果を次々に代入していけば全ての整数の平方根がもとめられます。
(複素数の計算の内部で sqrt を使っているのでは? というツッコミはあると思いますが無視してください)

Haskellではこのような記法はできません。
Data.Complex モジュールの

(:+)

というコンストラクターで複素数のインスタンスをつくります。
Haskellではコンストラクターは関数であり、(:+)は演算子として定義されているので次のようにします。

GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude> import Data.Complex
Prelude Data.Complex> let a=0:+1
Prelude Data.Complex> a
0 :+ 1
Prelude Data.Complex> let b=1:+0
Prelude Data.Complex> b
1 :+ 0

ちょっと不格好ですが・・・

Haskell は、複素数の絶対値を複素数で返します。

Prelude Data.Complex> abs(a-b)
1.4142135623730951 :+ 0.0

これは abs が
abs :: Num a => a -> a
と定義されているからです。
かわりにmagnitudeをつかいます。

Prelude Data.Complex> :t magnitude
magnitude :: RealFloat a => Complex a -> a

Prelude Data.Complex> magnitude(a-b)
1.4142135623730951

ちなみに Data.Complex では abs を
abs z               =  magnitude z :+ 0
と再定義しているようです。(^_^;)

N−1 の平方根がわかれば N の平方根が計算できることから再帰的に定義できます。

--r.hs
import Data.Complex
dist a b = magnitude (a-b)
a = 0 :+ 1
r 0 = 0
r n = dist a b
    where b = r (n-1) :+ 0


Prelude> :l r.hs
[1 of 1] Compiling Main             ( r.hs, interpreted )
Ok, modules loaded: Main.
*Main> map r [0..9]
[0.0,1.0,1.4142135623730951,1.7320508075688774,2.0,2.23606797749979,2.4494897427831783,2.6457513110645907,2.8284271247461903,3.0000000000000004]

容易に想像できると思いますがNが大きくなると時間がかかるようになります。

*Main> :set +s
*Main> r 1000000
1000.0000000000299
(7.74 secs, 1,673,363,512 bytes)

このような再帰は fold で置き換えることができます。

*Main> let r' n = foldl (\x _ -> dist a (x :+ 0)) 0 [1..n]
*Main> r' 1000000
1000.0000000000299
(5.28 secs, 1,474,441,216 bytes)

さらに Data.List モジュールの foldl'  を使うと

*Main> import Data.List
*Main Data.List> let r'' n = foldl' (\x _ -> dist a (x :+ 0)) 0 [1..n]
*Main Data.List> r'' 1000000
1000.0000000000299
(2.52 secs, 1,293,766,728 bytes)

magnitude 自体が重い処理なのでそこそこかかります。

fold を使ったコードは最初に説明した手続き的処理をそのまま置き換えている点に注目です。

手続き的なscanlの説明
参照

余談ですが (:+) の型は 

Prelude Data.Complex> :t (:+)
(:+) :: a -> a -> Complex a

です。引数の型は何でもいいようです。ですので

Prelude Data.Complex> "hello" :+ "world"
"hello" :+ "world"
Prelude Data.Complex> :t it
it :: Complex [Char]

もちろん演算とかはできません。

2017年12月9日土曜日

gist.github の罠

上のコードをコピペして実行する。

$ runghc a.hs

a.hs:3:11: error: Variable not in scope: n

たぶんこのようなエラーになるはずです。
最初はなぜエラーになるのか理解できませんでした。


Vim上ではまったく見た目は同じです。

カーソルをのせてみると違いがわかります。






show してみると

$ runghc b.hs
"n"
"\65358"

65358は、16進の"ff4e"
つまりUnicodeの小文字 n です。
対して2行目の n はアスキー。

これはコードを日本語入力がONのまま修正したことでおこりました。
見た目は同じでも異なる文字なのでエラーとなりました。

myPlayer

-- pipe.hs import System.Process import System.Environment main :: IO () a:_ IO [FilePath] randomize lst = do let c = length lst ...