スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

cabal windows インストールできない

既知のバグのようですが(以下参照)

http://hackage.haskell.org/trac/hackage/ticket/922



windows上でcabalを使ってhaskellのライブラリをインストールするときに失敗するのでメモ。

【エラーメッセージ】
“lexical error (UTF-8 decoding error)”

【対策】
事前にLANGを変更してからcabal installを使う
set LANG=C

【原因】
???
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

【Haskell】マンデルブロ集合

haskellで画像ファイルを作成したいなとふと思い立ったので、マンデルブロ集合を作成するプログラムをしました。
ビットマップを扱うライブラリは公開されてると思ったので調べてcabal を使ってダウンロード&インストール
発散するかどうかのチェックは|z|>2,発散速度は|z|>2になるまでの計算の繰り返し回数です。
とりあえず作ってみたので高速化なんて全然考えてないですが、それなりに1000*1000px程度を
一分程度の速度で描けたのでまあまあかな。
作ってて気になったのがHaskellってワンライナーで書きやすいので、横に長くなっちゃうstyleで
書いてしまって、後で型エラーとかで困ることが多多ありました。

拡張をかんがえると、
1:色の指定を外部ファイルから与えること
2:発散しない場合でも何かしらの色を付ける方法を考える
3:ライブラリ化

といったところですかね。
あ、あと高速化。



{-
-マンデルブロ集合描写プログラム
- 2012/12/22 作成
- author: t.k.
- version: 0.1.0
-}
import Codec.BMP
import Numeric
import qualified Data.ByteString as B
import GHC.Word
import Data.Complex
import Control.Monad.List
import System.IO
import System.Environment



-- 計算範囲 [(x.y) | x <- [x1..x2], y <- [y1..y2]]
--とするとき
--引数 x1 -> x2 -> y1 -> y2 -> width -> outputFilePath -> IO()
--
main :: IO()
main = do arg <- getArgs
let l = read (arg !! 0)
let r = read (arg !! 1)
let b = read (arg !! 2)
let t = read (arg !! 3)
let w = read (arg !! 4)
let f = arg !! 5
drowMandibrot2 (l,t) (r,b) w f


-- [[(R,G,B)]] の配列からビットマップのByteStringに変換する
rgbToByteList:: [[(Word8,Word8,Word8)]] -> B.ByteString
rgbToByteList = B.pack . concat . map rgbToByteList'
where rgbToByteList' = concatMap (\(r,g,b) -> [ r, g,b,0])
----------------------------------------------------------------------
{-
- マンディブロ集合
-}

-- マンデルブロ集合漸化式
mandibrotFunc :: (Num a) => a -> a -> a
mandibrotFunc c z = z*z + c


-- zの計算回数
count :: Int
count = 200

-- マンデルブロ集合の発散速度[1..count]からRGBの値を得る
-- 発散速度 -> RGB
toPixcel :: Int -> (Word8,Word8,Word8)
toPixcel z
| z == 0 = (0,0,0)
| count - z > 60 = (255,241,0)
| count - z > 30 = (00,30,68)
| count - z > 25 = (99,22,60)
| count - z > 20 = (125,100,120)
| count - z > 15 = (80,90,100)
| count - z > 8 = (125,180,120)
| count - z > 3 = (120,220,225)
| otherwise = (255,255,255)
{-
| z == 0 = (0,0,0)
| z < 10 = (30,30,30)
| z < 20 = (60,60,60)
| z < 40 = (120,120,120)
| z < 80 = (150,150,150)
| z < 90 = (180,180,180)
| otherwise = (255,255,255)
-}

-- マンデルブロ集合描写関数(最初に作ったのが使いにくインターフェースだったため改良)
-- (left,top) -> (right,bottom) -> width -> FilePath -> IO()
drowMandibrot2 :: (Double ,Double) -> (Double,Double) -> Int -> FilePath -> IO()
drowMandibrot2 (left,top) (right,bottom) w file = drowMandibrot (left,bottom) (w,h) dt file
where
dt = (right - left ) / (fromIntegral w)
h = truncate $ (top - bottom) / dt

-- マンデルブロ描写関数
-- 引数 (top,left) -> (width,heigth) -> dt -> FilePath -> IO()
drowMandibrot :: (Double ,Double) -> (Int,Int) -> Double -> FilePath -> IO()
drowMandibrot point size@(w,h) dt file = writeBMP file $ packRGBA32ToBMP w h $ rgbToByteList $! mandibrot point size dt


-- 複素平面上のマンデルブロ集合の発散速度を計算しRGBのリストを返す
mandibrot :: (Double ,Double) -> (Int,Int) -> Double -> [[(Word8,Word8,Word8)]]
mandibrot (left,top) (w,h) dt = map (map (toPixcel . calc ) ) $ numberList left top w h dt
where
-- マンデルブロ集合の発散速度を計算する
-- 引数 発散速度を計算する複素平面上の点 -> 発散速度
calc c = count - (length $ takeWhile ( \x -> (magnitude x) <=2) $ take count $ iterate (mandibrotFunc c ) 0 )
-- マンデルブロ集合を計算する複素平面上の点をすべて計算する
-- 引数 left 0 -> top -> width -> height -> dt
numberList left top w h dt = map (\x -> (take w (iterate ( +(dt:+0) ) $ (left:+0) + x))) $ take h $ iterate (+ ((0:+dt))) $ (left:+top)

テーマ : プログラミング
ジャンル : コンピュータ

逆ポーランド関数電卓

Haskell で逆ポーランド型の関数電卓(試作品)を作ってみました。
javaとかと違ってエラーを考慮して、型を定義しないといけないのでそれがちょっと面倒ですが、
面倒なのはそのくらいで基本的には楽にかけました。


{-
- 逆ポーランド型関数電卓
-
-}
import System.IO
import Data.Either
import Data.String
import Data.Maybe
import Data.List
import Data.Char

main :: IO()
main = getLine >>= calc
calc :: String -> IO()
calc str
| str == "q" = putStrLn str
| otherwise = putStrLn (calcCore ( parse $ words str)) >> main


parse :: [String] -> [Either String (Maybe Int)]
parse = map parse'
where
parse' :: String -> Either String (Maybe Int)
parse' str
| all isDigit str = Right (Just (read str))
| otherwise = Left str


calcCore :: [Either String (Maybe Int)]-> String
calcCore a = show $ head $ snd $ calcCore' (a,[])

calcCore' :: ([Either String (Maybe Int)],[Maybe Int]) -> ([Either String (Maybe Int)],[Maybe Int])
calcCore' ([],n) = ([],n)
calcCore' ((a:as), n) = calcCore' (as, (either (f1 n) (f2 n) a))

-- 演算子が入った時に演算する
f1 :: [Maybe Int] -> String -> [Maybe Int]
f1 (a:as) b = calc'' b a ( head as):tail as

-- スタックに積み込む
f2 :: [Maybe Int] -> Maybe Int -> [Maybe Int]
f2 a b = b:a


calc'' :: String -> Maybe Int -> Maybe Int -> Maybe Int
calc'' c (Just a) (Just b)
| c == "+" = Just ((+) a b)
| c == "-" = Just ((-) a b)
| c == "*" = Just ((*) a b)
| otherwise = Nothing
calc'' _ Nothing _ = Nothing
calc'' _ _ Nothing = Nothing

テーマ : プログラミング
ジャンル : コンピュータ

【つきいちHaskell】2回目 ファイル入出力(2)

ファイル入出力2


前回に引き続いてファイルIO関係を整理していきます。

ハンドラの情報を取得


ハンドラの情報を取得します。

-- 開いているかどうかのチェック
hIsOpen :: Handle -> IO Bool
-- 閉じているかどうかのチェック
hIsClosed :: Handle -> IO Bool
-- 読み込み可能かどうかのチェック
hIsReadable :: Handle -> IO Bool
-- 書き込み可能かどうかのチェック
hIsWritable :: Handle -> IO Bool
-- シーク(ランダムアクセス)可能かどうかのチェック
hIsSeekable :: Handle -> IO Bool
-- ターミナルデバイスにかどうかのチェック
hIsTerminalDevice :: Handle -> IO Bool


ターミナルディバイスってなんだろうと思いファイル、標準入力、標準出力
でチェックしたことろ、
標準入力と標準出力がTrueとなったので、標準入力と標準出力(標準エラー出力も?)みたいです。
その時のコードは以下です。

import System.IO

main :: IO ()
main = do
putStrLn"File (WriteMode)">> withFile "test.txt" WriteMode (handleProperty)
putStrLn "stdin" >> handleProperty stdin
putStrLn "stdout" >> handleProperty stdout


handleProperty :: Handle -> IO ()
handleProperty h = do
putStr "hIsOpen: " >> hIsOpen h >>= print
putStr "hIsClosed: " >> hIsClosed h >>= print
putStr "hIsReadable: " >> hIsReadable h >>= print
putStr "hIsWritable: " >> hIsWritable h >>= print
putStr "hIsSeekable: " >> hIsSeekable h >>= print
putStr "hIsTerminalDevice : " >> hIsTerminalDevice h >>= print



入出力に使う文字コードの変更


日本語のようにアルファベット以外の文字を扱う時に文字コードって結構重要で、文字化けの問題が起きたり起きなかったりするんですよね。windowsとUnix系で文字コードが違うためファイル名が文字化けしたりとか、ブラウザでダウンロードしたら中身のテキストファイルが読めなかったりとか色々起きます。
S-JISが扱えないみたいなので、windows上で扱う場合はテクニックを使う必要があるみたいです。Haskell から MultiByteToWideChar を呼び ShiftJIS←→UTF16 変換する

hSetEncoding :: Handle -> TextEncoding -> IO ()
hGetEncoding :: Handle -> IO (Maybe TextEncoding)


エンコーディング情報を取得するサンプルです。

import System.IO
main :: IO()
main = do
putStrLn "File::::" >> withFile "test.txt" WriteMode encoding
putStrLn "stdin:::" >> encoding stdin
putStrLn "stdout:::" >> encoding stdout
encoding :: Handle -> IO ()
encoding h = hGetEncoding h >>= print


私の環境(CentOS)だと以下のような出力結果になりました。

File::::
Just UTF-8
stdin:::
Just UTF-8
stdout:::
Just UTF-8

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

かみさまみならい

Author:かみさまみならい
FC2ブログへようこそ!

最近の記事
最近のコメント
最近のトラックバック
月別アーカイブ
カテゴリー
ブロとも申請フォーム

この人とブロともになる

ブログ内検索
RSSフィード
リンク
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。