Chap.4 Exercise 7 (今井け) まずはkとsの定義 # let k x y = x;; val k : 'a -> 'b -> 'a = <fun> # let s x y z = x z (y z);; val s : ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c = <fun> 問1. (s k k) == id の確認 s k k 1 ==> k 1 (k 1) (* sの定義より *) ==> c1 (k 1) (* ただし c1 は 必ず1を返す定数関数, c1 : 'b -> int *) ==> c1 c2 (* 同様に c2 : b' -> int *) ==> 1 s k k のそれぞれの部分式の型は? 仮に s1 k1 k2 とすると s1 : ('a1 -> ('b2 -> 'a1) -> 'a1) -> ('a1 -> 'b2 -> 'a1) -> ('a1 -> 'a1) k1 : 'a1 -> ('b2 -> 'a1) -> 'a1 k2 : 'a1 -> 'b2 -> 'a1 よって s1 k1 : ('a1 -> 'b2 -> 'a1) -> ('a1 -> 'a1), s1 k1 k2 : ('a1 -> 'a1). 問2. 'a -> 'b -> 'b なる関数をskのみで構成 答え.k (s k k) # k (s k k) 1 2;; - : int = 2 - それぞれの部分式の型は? s k k : 'a1 -> 'a1 (恒等関数). k : 'a -> 'b -> 'a だが,この 'a が s k k の 'a1 -> 'a1 と単一化され k : ('a1 -> 'a1) -> 'b -> ('a1 -> 'a1) という型が付く. よって k (s k k) : 'b -> 'a1 -> 'a1
ソース arity.hs
import Data.Typeable tyArr = fst $ splitTyConApp $ typeOf (?x->not x) arity :: (Typeable a) => a -> Int arity f = countArr (typeOf f) where countArr ty = case splitTyConApp ty of (tyCon, [_, tyRes]) -> if tyCon == tyArr then 1 + countArr tyRes else 0 _ -> 0
例
*Main> arity (&&) 2 *Main> arity (||) 2
(+) :: (Num a) => a -> a -> a だが,Num aから Typeable aは導出できない為,こっちで型を指定する必要がある
*Main> arity (+) <interactive>:1:0: Ambiguous type variable `a' in the constraints: `Typeable a' arising from use of `arity' at <interactive>:1:0-4 `Num a' arising from use of `+' at <interactive>:1:6-8 Probable fix: add a type signature that fixes these type variable(s) *Main> arity ((+)::Int->Int->Int) 2 *Main> arity True 0
let多相と値多相の他の例:
# let double f x = f (f x);; val double : ('a -> 'a) -> 'a -> 'a = <fun> # let f1 x = x +1;; val f1 : int -> int = <fun> # let x1 = 0;; val x1 : int = 0 こっちはOKのだけど # double double f1 x1;; - : int = 4 こっちは型付けできない. # (fun d -> d d f1 x1) double;; This expression (2つめのd) has type 'a -> 'b -> 'c -> 'd but is here used with type 'a 参考 # (fun d -> double d f1 x1) double;; - : int = 4 # (fun d -> d double f1 x1) double;; - : int = 4