wvogel日記

自分用の技術備忘録が多めです.

型付λ?

型付きλ計算って、こういうことなんだろうか

Prelude> :{
Prelude| let {
Prelude|      f::[String]->(Int,Int);
Prelude|      f = \(x:y:_) -> (read x,read y)
Prelude|     }
Prelude| :}
Prelude> f ["23","43"]
(23,43)


なんか違う気がする........


あと、上のfにおいて、

f.words "1 2 3"

ではerrorになったけど、

fwords = f.words
fwords "1 2 3"

と、引数を消して関数合成をしてやると通った。
なぜ?


どちらにしろ、同じことをしてると思うんだけど。
(.)の型は、

(.) :: (b -> c) -> (a -> b) -> a -> c

だから、前者でも後者でも通りそうなのに。
未だに(.)に関しては、正しい記述がよくわからない


コメントをいただき、朝ghciから指摘されたエラーの原因がとてもよくわかりました。
再びghciでの実験の様子

Prelude> :{
Prelude| let {
Prelude|     f :: [String]->(Int,Int);
Prelude|     f (a:b:_) = (read a, read b)
Prelude|     }
Prelude| :}
Prelude> f $ words "1 2 3"
(1,2)
Prelude> f. words "1 2 3"

<interactive>:1:4:
    Couldn't match expected type `a0 -> [String]'
                with actual type `[String]'
    In the return type of a call of `words'
    In the second argument of `(.)', namely `words "1 2 3"'
    In the expression: f . words "1 2 3" 

つまり、関数適用が何よりも優先されるHaskellにおいては、words "1 2 3"
が先に計算され、
(.)に対し、
(.) :: (b -> c) -> (a -> b) -> a -> c
つまりここでは
(.) :: ([String]->(Int,Int))->
(String->[String])->String->(Int,Int)
という引数をとるはずが、
f.words "1 2 3"
は実際には、無理やり型の様子を書くとすれば
([String]->(Int,Int))->[String]->(Int,Int)
のようにみなされたために、上のようなerrorが出たと。


なるほど!
とてもよく理解した。
またソースコード書いていく中でどんどん実践していこう