Hatena::Grouphaskell

[ pred x | x <- "Ibtlfmm!ojllj" ] RSSフィード

2007-01-18

しばらくパソコンから離れていました。疲れたのでですます調はゆるめにします。

instance Monad ((->) a)

HaskellWikiにあった一文。

(id >>= (+) >>= (+) >>= (+)) 3        -- (3+3)+(3+3) = 12
(join . liftM2) (*) (+3) 5            -- 64 

とても奇怪な式です。ghciに打ち込んでも出るのは見慣れた

add an instance declaration for (Monad ((->) a))

このメッセージ。つまりinstanceを書かないといけません。

returnとbindは

return :: a -> m a
a -> m a
  <=> a -> ((->) x) a
  <=> a -> (x -> a)
  <=> a -> x -> a

(>>=) :: m a -> (a -> m b) -> m b
m a -> (a -> m b) -> m b
  <=> ((->) x) a -> (a -> ((->) x) b) -> ((->) x) b
  <=> (x -> a) -> (a -> (x -> b)) -> (x -> b)
  <=> (x -> a) -> (a -> x -> b) -> x -> b
return :: a -> x -> a
(>>=) :: (x -> a) -> (a -> x -> b) -> (x -> b)

それぞれこういう具合の型になるでしょう。具体例から考えて

(return 1) "abc" <=> 1
id >>= (+) <=> (\x -> x + x)
id >>= return <=> (\x -> x)
instance Monad ((->) a) where
  return  = const
  g >>= f = \x -> f (g x) x

こういう結果になります。要は関数を適用しながらつなげていくものです。

*Main> (id >>= (+) >>= (+) >>= (+)) 3
12

無事動きました。


蛇足ですがfmapの方はおそらくこうだと思います。

fmap :: (a -> b) -> ((->) x) a -> ((->) x) b
  <=> (a -> b) -> (x -> a) -> (x -> b) 
instance Functor ((->) a) where
  fmap = (.)


もう一つ蛇足。do記法で書き換えてみると

triple = do
  x <- id
  y <- (x+)
  z <- (y+)
  return z

単なる機能の少ないStateのような気がします。(追記:これReaderですね)

謎のdjinn

lambdabotをローカルに飼おうとしてみてビルドに失敗したとき、サブディレクトリにdjinnという妙なものがあるのに気づきました。

Welcome to Djinn version 2005-12-15.
Type :h to get help.
Djinn>

起動できるようです。とりあえず言うとおり:hと打ってみると

Djinn is a program that generates Haskell code from a type.
Given a type the program will deduce an expression of this type,
if one exists.  If the Djinn says the type is not realizable it is
because there is no (total) expression of the given type.
Djinn only knows about tuples, ->, and some data types in the
initial environment (do :e for a list).
(snip)
type <sym> <vars> = <type>         Add a type synonym
data <sym> <vars> = <datatype>     Add a data type
<sym> :: <type>                    Add to environment
<sym> ? <type>                     Query
Djinnは型からHaskellのコードを生成するプログラムです。
与えられた型から式を(できれば)導きだすことができます。
"type is not realizable"と出るときは、与えた型の記述が充分でないということです。
Djinnは起動時にはタプルと(->)と少しの型しか知りません。(:eでリストが見られます)
...
type <sym> <vars> = <type>         type synonymを追加
data <sym> <vars> = <datatype>     data typeを追加
<sym> :: <type>                    環境に追加
<sym> ? <type>                     たずねる

本当なら夢のようなプログラムです。早速さっき苦労した型で聞いてみると

Djinn> return ? a -> x -> a
return :: a -> x -> a
return a _ = a
Djinn> bind ? (x -> a) -> (a -> x -> b) -> x -> b
bind :: (x -> a) -> (a -> x -> b) -> x -> b
bind a b c = b (a c) c
Djinn> fmap ? (a -> b) -> (x -> a) -> (x -> b)
fmap :: (a -> b) -> (x -> a) -> x -> b
fmap a b c = a (b c)

あっさり解いてしまいました。恐るべし。

意地悪な型を思いついた方は教えてください。djinnに聞いてみます。

Djinn> :e
data () = ()
data Either a b = Left a | Right b
data Maybe a = Nothing | Just a
data Bool = False | True
data Void
type Not x = x -> Void

:eはこういう具合です。(あまり無茶な型を与えるとNot xを出してくるようです)

トラックバック - http://haskell.g.hatena.ne.jp/illillli/20070118