Haskellの関数従属とは「ある型が決まれば別の型が一意に決まる」という依存関係のこと

使う時にはあまり気にならないが、「| m -> s」が関数従属性を定義しているらしい。

第6回 局所的な「状態」を利用するためのStateモナド

class (Monad m) => MonadState s m | m -> s where
    get :: m s
    put :: s -> m ()

結局コレは何かというと以下のエントリが参考になる。

この「| a -> v」の部分は「aを引数に取りvを返す関数」ではなく、型同士の依存関係を関数形式で記述したものです。意味としては「aが決まればvの型が一意に定まる」ことを意味しています。型クラスにおける関数従属

具体例は関数従属の背景で丁寧に解説されているが、型推論の際の曖昧性の排除を目的としているという理解でいいのかな。

参考

Haskell外部ライブラリの型をShowクラスのインスタンスにしてデバッグを楽にする

外部ライブラリを使っていてプリントデバッグをしたい時に、型がShowクラスのインスタンスになってないと印字されないので困る。

そういう時には、StandaloneDeriving拡張を使って外付けでderiving instance Showすればいい。

が、全てにderiving instance Showするようなデバッグ用オプションがあってもいいような気もするが。

Template Haskellと準クォートのお勉強

Template Haskellと準クォートの違いがわからないというか全体的にぼやけた理解というかあまり理解していなかった(THの説明見ているとTH=QQみたいな印象を持ってしまうので区別がつかない)ので、3連休の最終日はTHってた。

ちょっと前にモナド内包表記で遊んでいたので、

[|...|]

とかいう記法はなんかの型に入っているイメージが湧いてくる。

要するにLispに例えるとTemplate Haskellはマクロで準クォートがリーダーマクロだという感じの理解で良いのだろうかね。

ProductName On Lisp
ポール グレアム
オーム社 / 3990円 ( 2007-03 )


Yesod無しでHamletを使う

sofのコードは動かなかった

  • Text.Blaze.Renderer.Stringは廃止なのでText.Blaze.Html.Renderer.String
  • HamletじゃなくてHtmlUrl

この二点を直したら動いた

{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}

import Data.Text
import Text.Blaze.Html.Renderer.String (renderHtml)
import Text.Hamlet

data Url = Haskell | Yesod

renderUrl Haskell _ = pack "http://haskell.org"
renderUrl Yesod   _ = pack "http://www.yesodweb.com"

title = pack "This is in scope of the template below"

template :: HtmlUrl Url
template = [hamlet|
<html>
    <head>
        #{title}
    <body>
        <p>
            <a href=@{Haskell}>Haskell
            <a href=@{Yesod}>Yesod
|]

main = do
    let html = template renderUrl
    putStrLn $ renderHtml html

hamletのシンタックスは先頭がタグなので、普段Jade使っている僕にとっては似てるけどなんか変だなという印象だ。しかし、Jadeは先頭の文字列の区別が予約語(ifとか)、それ以外の記号で始まらない文字列はタグになるので、込み入ったテンプレートは結構読みにくい。

なので、タグで区別できるHamletのほうが可読性がいいのかな。

インラインのタグを入れ子にしたい場合には、エスケープの処理とかしないといけないのはインデント系に共通の読みにくさかも。あと条件演算子を入れると同じレベルのliなんかでもインデントが1つ下がるので、ちょっと読みにくくなってしまうところも一緒かな。

Hamletでヨサゲなのはテンプレート中でMaybeとかCase式が使えるところかな。

なんか作ってみたくなってきた。

ProductName Developing Web Applications With Haskell and Yesod
Michael Snoyman
Oreilly & Associates Inc / 2805円 ( 2012-05-04 )


Haskell Platformをアンインストールして綺麗な環境を取り戻す

なぜか/usr/local/binのcabal(2010年製)を使っていたり、依存関係がぐちゃぐちゃになってしまい、Yesod入れようとしたら目眩のするようなエラーリストが生成されたりとグッタリ感満載の環境になってしまった。

全てをなかったことにしたいが、完全にきれいにするアンインストーラーは用意されてないみたいなのでそれっぽいのを消していく。

sudo /Library/Frameworks/GHC.framework/Versions/Current/Tools/Uninstaller
sudo rm -rf /Library/Frameworks/HaskellPlatform.framework
rm -rf ~/.cabal
rm -rf ~/.ghc

/usr/binのシンボリックリンクとかも消せばいいんだろうけどもう一度インストールするので放っておいた。

(注) Haskell-Platform-2012.2.0.0には/Library/Haskell/bin/uninstall-hsというコマンドが用意されてました。

入れなおす。cabalを新しくしたらすぐにvirthualenvを入れる(超重要)。

open Haskell\ Platform\ 2012.2.0.0\ 32bit.pkg 
cabal update
cabal install cabal-install-0.14.0 #0.16.0はvirthualenvがバグる
cabal install virthualenv

新しいパッケージなんかを試したくなたらサンドボックスをつくる。例えばyesodを使いたい場合、適当なディレクトリを掘ってvirthualenvコマンドを叩くと.virthualenvディレクトリが出来てそこにcabalとか色々な設定がされる。

mkdir yesodtest
cd yesodtest
virthualenv

サンドボックス環境にするにはactivateする

source .virthualenv/bin/activate
cabal install yesod-platform

サンドボックス環境から抜けるにはdeactivateコマンドを叩けばいいし、要らなくなったら.virthualenvディレクトリを消せばいいだけなので、精神的によろしい。

Haskellの一般化代数データ型(GADT)

GADTs使ってみたを読んだらわかりやすかったので、適当なサンプルを見つけてみた。

プログラミングHaskell10.5の仮想マシンを例に取る

data Expr = Val Int | Add Expr Expr

value :: Expr -> Int
value (Val n) = n
value (Add x y) = value x + value y

GADTで書き直すと

data Expr where
    Val :: Int -> Expr
    Add :: Expr -> Expr -> Expr

value :: Expr -> Int
value (Val n) = n
value (Add x y) = value x + value y

データコンストラクタが、型をとって型を返す関数のように表現できる。

実行するにはGADTs拡張をつける

$ ghci -XGADTs vmachine2.hs 
GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( vmachine2.hs, interpreted )
Ok, modules loaded: Main.
*Main> value (Add (Val 3) (Val 2))
5

ProductName プログラミングHaskell
Graham Hutton
オーム社 / 2940円 ( 2009-11-11 )


Haskellerも順調に増加している

HaskellのType Familiesがわからんよ(改めわかった)

Yesodの本を読んでいて、Type Familiesでいきなり躓いた。

1349308784

class SafeHead a where
    type Content a
    safeHead :: a -> Maybe (Content a)

の type Content aでContentってなんで必要なの?という。

Content a :: *

なんだろうけど

a :: *

にはならんのかね?

ProductName Developing Web Applications With Haskell and Yesod
Michael Snoyman
Oreilly & Associates Inc / 2805円 ( 2012-05-04 )


追記 2012.10.04

@koyama41教えてもらった

「型引数を取って結果の型を返す、型レベルの関数」という表現から抽象への理解がぱっと上がった気がする。

わかってしまうと最初の方の疑問は寝ぼけたものだった。Haskell面白い。

Haskellのモナド内包表記(リスト内包表記じゃないよ)

リスト内包表記とリストモナドのdo表記の関係性がわからない場合にはReal World Haskell 14章のUnderstanding the list monadか、すごいHaskellの13章を読んでおくと良いです。

ProductName すごいHaskellたのしく学ぼう!
Miran Lipovača
オーム社 / 2940円 ( 2012-05-23 )


モナド内包表記

栄光のグラスゴーHaskellコンパイルシステム利用の手引き バージョン7.4.2 (7.3.11)

モナド内包表記はリスト内包表記をあらゆるモナドに一般化したものである。これには並列内包表記(7.3.9. 並行リスト内包表記)と変換内包表記(7.3.10. 一般化(SQL風)リスト内包表記)を含む。

MonadComprehensions拡張を有効にして呼び出す。分かりやすいMaybeモナドで

$ ghci -XMonadComprehensions
GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
Prelude> 
Prelude> [x+y | x <- Just 5, y<- Just 3]
Just 8
Prelude> [x+y | x <- Just 5, y<- Nothing]
Nothing

Maybe箱に入って出てきますね。MaybeはもちろんMonadPlusのインスタンスなのでガードが使える。

Prelude> [x+y | x <- Just 5, y<- Just 3, x < 3]
Nothing

続いてEitherを。これはControl.Monad.Errorを使う。

Prelude> :m +Control.Monad.Error
Prelude Control.Monad.Error> [ x+y | x <- Right 5, y <- Right 3]
Right 8
Prelude Control.Monad.Error> [ x+y | x <- Left "not a number", y <- Right 3]
Left "not a number"

Stateモナドだってできるぞ。

Prelude Control.Monad.State> runState [x | x <- get] 3
(3,3)

しかしこれは読みにくい。

Nexus 7が到着した

Fedexは宅配ボックスに入れておいてくれないとか再配達に同期するタイミングがつかめないとかプチトラブルはあったけど無事に到着した。

1349257804

軽いし片手で持てるので電子書籍リーダーとして使うには良い感じかも。

早速Yesodのepubを購入した。

1349257806

そして読む

PLEAC18.1&18.2をHaskellで

三島Haskell無名関数の会でHaskell熱が復活したので、PLEACをちょっとやってみた。

mapM inet_ntoa =<< liftM hostAddresses (getHostByName "google.co.jp")

こういうのをbind使わず俳句を読むようにスラスラ書けるようになりたいものだ。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan
オライリージャパン / 3990円 ( 2009-10-26 )