 
 substituteList = (substitution, list) ->
   map ((t) -> substitute substitution, t), list
+
+# Only valid for substitute
+mapToSubstitution = (map) ->
+  vars: map.values
 
 findFree = (type) ->
   if type instanceof TypeVariable

          (jsNew identifier, []))
      (join (translateDict identifier, paramNames), [constrValue]))

findDataType = (ctx, types, typeParams, dataName) ->
  varNames = map _symbol, typeParams
  varNameSet = arrayToSet varNames
  kinds = newMap()
  for type in types
    for name, kind of values findFree typeCompile ctx, type
      if not inSet varNameSet, name
        malformed type, "Type variable #{name} not declared"
      else
        if foundKind = lookupInMap kinds, name
          if not kindsEq foundKind, kind
            malformed type, "Type variable #{name} must have the same kind"
        else
          addToMap kinds, name, kind

  for typeParam in typeParams
    if not lookupInMap kinds, (_symbol typeParam)
      malformed typeParam, 'Data type parameter not used'

  dataKind = kindFnOfArgs (map ((name) -> lookupInMap kinds, name), varNames)...
  typeVars = mapToArrayVia ((name, kind) -> new TypeVariable name, kind), kinds
  applyKindFn (new TypeConstr dataName, dataKind), typeVars...


ms.record = ms_record = (ctx, call) ->
    args = _arguments call

    # Syntax
    [names, typeArgLists] = unzip defs
    map (syntaxNewName 'Type constructor name required'), names
    if not hasName
      return 'malformed'

    dataName = ctx.definitionName()

    # Types, Arity
    {fieldTypes, dataType} = findDataType ctx, typeArgLists, typeParams, dataName
    for [constr, params], i in defs
      paramTypes = fieldTypes[i]
      constrType = if params
        typeFn (join paramTypes, [dataType])...
      else
        dataType
      paramLabels = (_labeled _terms params or []).map(_fst).map(_labelName)
      # log "Adding constructor #{constr.symbol}", constrType
      log printType constrType
      ctx.declare constr.symbol,
        type: quantifyUnbound ctx, toConstrained constrType
        arity: (paramLabels if params)
