structure signature functor

この3つはSML最大の難所だった。というのは当時はC言語しか知らなかったから。JavaC++(のtemplate)を理解してたらずっと理解しやすかったに違いない。structureはクラス、signatureはインタフェース、functorはパラメトリッククラスって割り当てて進めていく感じで。もちろんstructureはインスタンスの型定義ってわけだけでもないんだけど。

ocamlではstructureはmoduleらしい。意味はこっちのほうがわかりやすいかも。
例:

module MyLinkList = 
  struct 
    type 'a myList = Empty | Node of 'a * 'a myList
    
    exception ListIsEmpty
    
    let newList = Empty
    
    let rec add this item = 
      match this with
        Empty -> Node(item, Empty) |
        Node(value, trailer) -> Node(value, (add trailer item))
    
    let rec get this index =
      match this with
        Empty -> raise ListIsEmpty |
        Node(value, trailer) ->
          if index = 0 then value
          else (get trailer (index - 1))
    
  end;;


let my_list = MyLinkList.newList;;
let my_list = MyLinkList.add my_list 0;;
let my_list = MyLinkList.add my_list 10;;
let my_list = MyLinkList.add my_list 20;;
let my_list = MyLinkList.add my_list 30;;

open Printf;;
printf "index 2 of my_list is %d\n" (MyLinkList.get my_list 2);;

signatureはmodule typeでこちらも意味がわかりやすい。

module type MyList =
  sig
    type 'a myList
    
    exception ListIsEmpty
    
    val newList : 'a myList
    
    val add : 'a myList -> 'a -> 'a myList
    
    val get : 'a myList -> int -> 'a
    
  end;;

module MyLinkList : MyList = 
  struct 
    type 'a myList = Empty | Node of 'a * 'a myList
    
    exception ListIsEmpty
    
    let newList = Empty
    
    let rec add this item = 
      match this with
        Empty -> Node(item, Empty) |
        Node(value, trailer) -> Node(value, (add trailer item))
    
    let rec get this index =
      match this with
        Empty -> raise ListIsEmpty |
        Node(value, trailer) ->
          if index = 0 then value
          else (get trailer (index - 1))
    
  end;;


let my_list = MyLinkList.newList;;
let my_list = MyLinkList.add my_list 0;;
let my_list = MyLinkList.add my_list 10;;
let my_list = MyLinkList.add my_list 20;;
let my_list = MyLinkList.add my_list 30;;

open Printf;;
printf "index 1 of my_list is %d\n" (MyLinkList.get my_list 1);;

functorはパラメタライズされたmoduleで

module type MyList =
  sig
    type 'a myList
    
    exception ListIsEmpty
    
    val newList : 'a myList
    
    val add : 'a myList -> 'a -> 'a myList
    
    val get : 'a myList -> int -> 'a
    
  end;;

module MyLinkList : MyList = 
  struct 
    type 'a myList = Empty | Node of 'a * 'a myList
    
    exception ListIsEmpty
    
    let newList = Empty
    
    let rec add this item = 
      match this with
        Empty -> Node(item, Empty) |
        Node(value, trailer) -> Node(value, (add trailer item))
    
    let rec get this index =
      match this with
        Empty -> raise ListIsEmpty |
        Node(value, trailer) ->
          if index = 0 then value
          else (get trailer (index - 1))
    
  end;;

module MyListList : MyList = 
  struct 
    type 'a myList = 'a list
    
    exception ListIsEmpty
    
    let newList = []
    
    let rec add this item = 
      match this with
        [] -> [item] |
        value :: trailer -> value :: (add trailer item)
    
    let rec get this index =
      match this with
        [] -> raise ListIsEmpty |
        value :: trailer ->
          if index = 0 then value
          else (get trailer (index - 1))
    
  end;;

open Printf;;

module TestMyList (AnyMyList : MyList) =
  struct
    let createList =
      let my_list = AnyMyList.newList in
      let my_list = AnyMyList.add my_list 0 in
      let my_list = AnyMyList.add my_list 10 in
      let my_list = AnyMyList.add my_list 20 in
      let my_list = AnyMyList.add my_list 30 in
      my_list
   
   let print2nd my_list =
      printf "index 1 of my_list is %d\n" (AnyMyList.get my_list 1)
   
  end;;

module TestMyLinkList = TestMyList(MyLinkList);;
let my_list = TestMyLinkList.createList;;
TestMyLinkList.print2nd my_list;;