MokkosuでHaskellの型システムを作る (その3)

# はじめに

Simon Peyton Jones 論文 Typing Haskell in Haskell を参考に Haskell の型システムの実装に挑戦しています。実装には関数型言語の [Mokkosu](http://lambdataro.sakura.ne.jp/mokkosu/) を使っています。

* [Mark P Jones: Typing Haskell in Haskell](http://web.cecs.pdx.edu/~mpj/thih/)
* [MokkosuでHaskellの型システムを作る (その1)](http://qiita.com/lambdataro/items/1e4d795d3dd97a94c8f3)
* [MokkosuでHaskellの型システムを作る (その2)](http://qiita.com/lambdataro/items/c19e0d6d637e0dbb52ca)

# 型クラス (続き)
```
fun by_super ce (~IsIn(i,t) as p) =
  p :: concat (for i2 <- super ce i in by_super ce (IsIn(i2,t)));

let mplus_maybe m1 m2 =
  match (m1, m2) {
    (~Nothing, ~Nothing) -> Nothing;
    (~Just(x), ~Nothing) -> Just(x);
    (~Nothing, ~Just(x)) -> Just(x);   
    (~Just(x), ~Just(_)) -> Just(x);
  };

fun msum_maybe = {
  [] -> Nothing;
  x :: xs -> x `mplus_maybe` msum_maybe xs
};

let by_inst ce (~IsIn(i,t) as p) =
  let try_inst ~Qual(ps,h) =
    match (match_pred h p) {
      ~Nothing -> Nothing;
      ~Just(u) ->
        Just (map (apply_pred u) ps)
    }
  in
  msum_maybe (for ~Inst(it) <- insts ce i in try_inst it);

fun mem_pred_list p lis =
  match lis {
    [] -> false;
    p1 :: rest -> pred_equal p p1 && mem_pred_list p rest
  };

fun entail ce ps p =
  any (mem_pred_list p) (map (by_super ce) ps) ||
  (match (by_inst ce p) {
     ~Nothing -> false;
     ~Just(qs) -> all (entail ce ps) qs
   });

let in_hnf ~IsIn(_,t) =
  fun hnf = {
    ~TVar(v) -> true;
    ~TCon(tc) -> false;
    ~TAp(t,_) -> hnf t
  } in hnf t;

fun to_hnfs ce ps =
  concat (map (to_hnf ce) ps)

and to_hnf ce p =
  if in_hnf p -> [p]
  else
    match (by_inst ce p) {
      ~Nothing -> error "context resuction";
      ~Just(ps) -> to_hnfs ce ps   
    };

let simplify ce =
  fun loop rs = {
    [] -> rs;
    p :: ps ? entail ce (rs ++ ps) p -> loop rs ps;
    p :: ps -> loop (p :: rs) ps
  }
  in loop [];

let reduce ce ps =
  simplify ce <| to_hnfs ce ps;

let sc_entail ce ps p =
  any (mem_pred_list p) (map (by_super ce) ps);

#------------------------------
# 8. Type Schemes
#------------------------------

type Scheme = Forall ([Kind], Qual<Type>);

let kind_list_equal ks1 ks2 =
  all (uncurry kind_equal) (zip ks1 ks2);

let scheme_euqal sc1 sc2 =
  match (sc1, sc2) {
    (~Forall(ks1,q1), ~Forall(ks2,q2)) ->
      kind_list_equal ks1 ks2 && qual_equal_type q1 q2 
  };

let apply_scheme s ~Forall(ks,qt) =
  Forall(ks, apply_qual_type s qt);

let tv_scheme ~Forall(ks,qt) = tv_qual_type qt;

let quantify vs qt =
  let vs2 = for v <- tv_qual_type qt;
                if mem_tyvar_list v vs in v
  in
  let ks = map kind_tyvar vs2 in
  let s = Subst (zip vs2 (map TGen (0 .. length vs2))) in
  Forall (ks, apply_qual_type s qt);

let to_scheme t =
  Forall([], Qual([], t));
```

# 仮定
```
type Assump = Assump(Id, Scheme);

let apply_assump s ~Assump(i,sc) =
  Assump(i, apply_scheme s sc);

let tv_assump ~Assump(i,sc) = tv_scheme sc;

fun find (~Id(s) as i) = {
  [] -> error <| "unbound identifier: " ^ s;
  ~Assump(i2, sc) :: rest ->
    if id_equal i i2 -> sc
    else find i rest
};
```

# 型推論の状態
```
let subst = ref null_subst;
let count = ref 0;

let get_subst () = !subst;

let ext_subst s2 =
  subst := s2 `append_subst` !subst;

let unify t1 t2 =
  let s = get_subst () in
  let u = mgu (apply_type s t1) (apply_type s t2) in
  ext_subst u;

let new_tvar k =
  let n = !count in
  do incr count in
  TVar (Tyvar (enum_id n, k));

fun inst_type ts = {
  ~TAp(l,r) -> TAp(inst_type ts l, inst_type ts r);
  ~TGen(n) -> nth ts n;
  t -> t
};

let inst_pred ts ~IsIn(c,t) =
  IsIn(c, inst_type ts t);
  
let inst_pred_list ts ps =
  map (inst_pred ts) ps;
  
let inst_qual ts ~Qual(ps,t) =
  Qual(inst_pred_list ts ps, inst_type ts t);


let fresh_inst ~Forall(ks,qt) =
  let ts = map new_tvar ks in
  inst_qual ts qt;
```

# ここまでの感想
* もはや何のプログラムを書いているのか自分でも理解していない。

つづく