Is there a way, to write a polymorphic function (in sml), that calls itself with arguments of different type than the arguments it has got?
For example, I was looking on this answer, (it has the declaration datatype ('a,'b)alterlist = Nil| element of 'a*('b,'a)alterlist;) and intuitively, I would like to implement the function unzip, as:
fun unzip Nil = ([],[]) |
unzip (element(x,l)) = let val (b,a)=unzip l in (x::a,b) end;
The type inference system understands it as ('a,'a) alterlist -> 'a list * 'a list, but I want something of type ('a,'b) alterlist -> 'a list * 'b list (such that the inner call is to a ('b,'a) alterlist -> 'b list * 'a list)
I believe what you are asking for is polymorphic recursion, which is not implemented in standard ML.
This is however implemented in Haskell (and as #seanmcl pointed out, ocaml):
import Prelude hiding(unzip)
data Alterlist a b = Nil | Elem a (Alterlist b a)
unzip :: Alterlist a b -> ([a], [b])
unzip Nil = ([], [])
unzip (Elem x l) =
let (b, a) = unzip l
in (x : a, b)
x = Elem 1 (Elem True (Elem 5 (Elem False Nil)))
*Main> unzip x
([1,5],[True,False])
Related
As the title suggests, I want to write a function that takes in an 'a list and an expression that evaluates to either true or false when elements of the list are passed into it. The function should return an 'a list of all the elements that don't satisfy the predicate given. The type should be
'a list -> ('a -> bool) -> 'a list
when it is working properly.
This is what I have so far,
let rec filter (x: 'a list) pred =
if x = [] then [] else
if x -> pred = true then remove_if (x.tl) pred else
x :: xs remove_if (x.tl) pred ;;
I tried some other ways of writing it but in my closest attempt the type ended up evaluating improperly.
Here's something to get you started..
let rec filter f lst =
match lst with
| [] -> []
| hd::tl ->
if (f hd)
(*The rest of the function goes here*)
I have found an impletantion of a dictionary and your implementation. I want to create a dictionary using those modules below, but I'm getting this error:
Unbound Value.
I'm new to the functional paradigm. I tried this book, but I'm still lost: http://dev.realworldocaml.org/maps-and-hashtables.html
And
Dictionary and AssociateList from here: https://www.cs.cornell.edu/courses/cs3110/2014sp/recitations/7/functional-stacks-queues-dictionaries-fractions.html
let x = Dictionary.AssocList.create ;;
open Dictionary.AssocList
enviroment = create()
Unbound type constructor stringAssocListAssocList
module type DICTIONARY =
sig
(* An 'a dict is a mapping from strings to 'a.
We write {k1->v1, k2->v2, ...} for the dictionary which
maps k1 to v1, k2 to v2, and so forth. *)
type key = string
type 'a dict
(* make an empty dictionary carrying 'a values *)
val make : unit -> 'a dict
(* insert a key and value into the dictionary *)
val insert : 'a dict -> key -> 'a -> 'a dict
(* Return the value that a key maps to in the dictionary.
* Raise NotFound if there is not mapping for the key. *)
val lookup : 'a dict -> key -> 'a
exception NotFound
(* applies a function to all the elements of a dictionary;
i.e., if a dictionary d maps a string s to an element a,
then the dictionary (map f d) will map s to f(a). *)
val map : ('a -> 'b) -> 'a dict -> 'b dict
end
module AssocList : DICTIONARY =
struct
type key = string
type 'a dict = (key * 'a) list
(* AF: The list [(k1,v1), (k2,v2), ...] represents the dictionary
* {k1 -> v1, k2 -> v2, ...}, except that if a key occurs
* multiple times in the list, only the earliest one matters.
* RI: true.
*)
let make() : 'a dict = []
let insert (d : 'a dict) (k : key) (x : 'a) : 'a dict =
(k, x) :: d
exception NotFound
let rec lookup (d : 'a dict) (k : key) : 'a =
match d with
| [] -> raise NotFound
| (k', x) :: rest ->
if k = k' then x
else lookup rest k
let map (f : 'a -> 'b) (d : 'a dict) =
List.map (fun (k, a) -> (k, f a)) d
end
Assume that your dictionary implementation is saved in a file named dictionary.ml. To use this module, you would open it, and gives AssocList a shorter name for convenient (optional)
open Dictionary
module D = AssocList
To create a new, empty dictionary, you'll do:
let dict = D.make ()
To insert element, and make a new dict out of that, you'll do:
let new_dict = D.insert dict "one" 1
"one" is the key and 1 is the value.
If you want to see all elements in the dictionary, you'll have to make a new function, or make the (key * 'a) list type available, something like this in your signature
type 'a dict = (key * 'a) list (* This will make dict elements available *)
type 'a dict (* This will make the dict available but you can't view the elements *)
I prepare for GATE Exam. one of the oldest question is unfamiliar with us. some experts please clarify this for us.
Which of the following can be a type for following ML function ?
my f(g, nil)=nil | f(g,x::xs)=(fn a ⇒ g(a,x))::f(g, xs);
1) (int *book → real) * bool list → (int → real) list
2) (bool *int → int) * real list → (bool → int) list
3) (int *int → real) * real list → (real → bool) list
4) (bool *real → int) * int list → (int → int) list
The Answer Sheets say (1) Is corrects. comments or short description for better understanding?
One of the first things you should do is rewrite the function definition yourself. This will force you to actually parse and understand it.
fun f (g, nil) = nil
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
So, f is a function, even the question says that, it must have type ... -> ...:
val f : ... -> ...
What does it receive? Let's take a look at the first pattern of the function:
fun f (g, nil) = nil
It's something of the form (a, b), which is a 2-tuple. The function's argument must be a tuple then:
val f : (... * ...) -> ...
Just by looking at the definition, we can't figure out what type g must have, but it uses nil for the second element of the tuple and nil is the empty list. That means the second component of the tuple must be a list of something:
val f : (... * ... list) -> ...
What else can we deduce? The return value is nil as well, which means that the function returns a list of something, unclear what that something is yet.
val f : (... * ... list) -> ... list
Ok, let's jump to the second pattern of the function definition now:
| f (g, x :: xs) = (fn a => g (a, x)) :: f (g, xs);
We don't find anything more about the type of the argument, we just got confirmation that the second element of the tuple must indeed be a list, because it uses the :: constructor.
Let's take a look at the body:
(fn a => g (a, x)) :: f (g, xs)
It looks like it's building a list, so it must return a list, which is in accordance with the return type we've sketched so far, i.e., ... list. Let's
try to figure out the type of elements.
It seems to add a function object as the head of the list built by recursively calling the function f, which we're currently investigating. So the elements of the list we're returning must be functions:
val f : (... * ... list) -> (... -> ...) list
What does that function do, though? It calls g with a 2-tuple argument. Now we can fill in some information about the first element of the 2-tuple f receives. It must be a function that receives a 2-tuple as well:
val f : (((... * ...) -> ...) * ... list) -> (... -> ...) list
Can we say anything about the a parameter received by the function literal added to the return list? Not really, just that it's passed to g. Can we tell anything about the type of x? Not really, just that it's passed to g. Moreover, is there any constraint between a and x? Doesn't look like it. So far, we can only tell that g's type must be looking something like this:
('a * 'b) -> 'c'
Where 'a, 'b and 'c are polymorphic types, i.e., any concrete type can satisfy them. You can view them as wholes. We can now fill in more of the type for the f function:
val f : ((('a * 'b) -> 'c) * ... list) -> (... -> ...) list
We can do more actually, we've already assign a type to the x variable, but that comes from the second argument of the 2-tuple received by f, so let's fill in that too:
val f : ((('a * 'b) -> 'c) * 'b list) -> (... -> ...) list
And we can even fill in the element type of the returned list, because we've already assigned types for that, too.
val f : ((('a * 'b) -> 'c) * 'b list) -> ('a -> 'c) list
We can remove some extra parenthesis from the type we came up with without changing the meaning, because of the type operator precedence rules:
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
Now, our function's type is complete. However, this type can't be found in the list of possible answers, so we'll have to see if any of them can be used instead of what we've determined. Why? Because our function type uses type variables, which can be filled in by concrete types. Let's take them one by one:
Choice 1
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (int * bool -> real) * bool list -> (int -> real) list
It looks like 'a could be int, 'b could be a bool (it's book in what you've pasted, but I'm assuming it was a typo) and 'c could be a real. All the replacements match these correspondences, so we declare that, yes, the first choice can be a possible type for the given function, even though not the most general. Let's take the second choice:
Choice 2
val f : ('a * 'b -> 'c) * 'b list -> ('a -> 'c) list
val f : (bool * int -> int) * real list -> (bool -> int) list
The type-variable to concrete -type correspondence table could be this:
'a -> bool
'b -> int
'c -> int
'b -> real
We can stop here because we can see that 'b was assigned to different types, so this function signature can't be assigned to the implementation we've been given.
Choice 3 and 4
They are similar to choice 2, but I'll let them as an exercise to the reader :)
I am new to Ocaml and am writing code to substitute elements in nested Ocaml lists. My code is as follows:
type 'a sexp = S of 'a | L of 'a sexp list
My substitution function(it replaces all occurrences of element a with b in nested lists) is as follows:
let rec subst a b list = match list with
| [] -> list
| S s :: t -> if s = a then (S b) :: (subst a b t) else (S s) :: (subst a b t)
| L l :: t -> (subst a b l) :: (subst a b t)
Despite multiple attempts(for nearly 6 hours), I have not been able to compile this code.. Please help!
Can I suggest to first write a function subst of type 'a -> 'a -> 'a sexp -> 'a sexp instead? It would read
let subst x y sexp =
let rec visit = function
| S z -> S (if z = x then y else z)
| L sexps -> L (List.map visit sexps)
in
visit sexp
and arguably nicely and idiomatically captures the idea of recursing over an sexp.
Now, to obtain a function to operate on lists rather than single sexps, you can easily define a function subst_list of type 'a -> 'a -> 'a sexp list -> 'a sexp list:
let subst_list x y sexps = List.map (subst x y) sexps
Even nicer is to abstract away from substitution and have a more generally applicable function map of type ('a -> 'b) -> 'a sexp -> 'b sexp for performing structure-preserving mappings of sexps:
let map f sexp =
let rec visit = function
| S x -> S (f x)
| L sexps -> L (List.map visit sexps)
in
visit sexp
And then define subst in terms of map and subst_list, as before, in terms of subst:
let subst x y sexp = map (fun z -> if z = x then y else z) sexp
let subst_list x y sexps = List.map (subst x y) sexps
Note: using an F# compiler here; I don't have an OCaml compiler on this computer.
The last line of your subst function has an error: It should be as follows:
| L l :: t -> L (subst a b l) :: (subst a b t)
So the complete code would look like this:
type 'a Sexp =
| S of 'a
| L of 'a Sexp list
let rec subst (a) (b) (lst : 'a Sexp list) =
match lst with
| [] -> lst
| S s :: t -> if s = a then (S b) :: (subst a b t) else (S s) :: (subst a b t)
| L l :: t -> L (subst a b l) :: (subst a b t)
let test () =
let (lst : int Sexp list) = [S 1; L [S 2; L [S 3]; S 4]; S 5]
let a = 2
let b = 3
subst a b lst
The output of test() is
[S 1; L [S 3; L [S 3]; S 4]; S 5]
The reason is that your function subst returns a 'a Sexp list. If you omit the L constructor from the last line, then subst a b l is of type 'a Sexp list, which you are attempting to cons with another list of type 'a Sexp list. This does not work.
Nor was this your intention, since you wanted to end up with an entity of type 'a Sexp list, which means you must cons an element of type 'a Sexp with a list of type 'a Sexp list. By specifying the L constructor, you are creating an element of type 'a Sexp list, which you can now cons with the rest of the list.
It looks like your function subst is supposed to return something of type 'a sexp list. That's what the first and second match cases return.
In the third match case, then, your returned value is:
(subst a b l) :: (subst a b t)
Since your function returns 'a sexp list, this type doesn't make a lot of sense. The head of the list is of type 'a sexp list and the tail of the list is also of type 'a sexp list. It's very difficult to come up with any lists that have this kind of structure. I think what you want is for the head of the list to be of type 'a sexp.
If you want the head of the list to be of type 'a sexp, you need some way of packaging up a list of things into a single 'a sexp. If this isn't enough of a hint, look at your L constructor. That's exactly what it does.
Functors in Standard ML are related to the module system and can generate structures based on other structures. An example of a functor generating list combinators for various types of lists is given below, but this example has a problem:
The various types of lists all have advantages -- for example, lazy lists can be infinitely long, and concantenation lists have a O(1) concat operator. But when all of these list types conform to the same signature, the functor can only use their general properties.
My question is therefore: What is a good example of when functors are useful and the various generated structures don't lose their special abilities?
signature MYLIST =
sig
type 'a t
val null : 'a t -> bool
val empty : 'a t
val cons : 'a * 'a t -> 'a t
val hd : 'a t -> 'a
val tl : 'a t -> 'a t
end
structure RegularList : MYLIST =
struct
type 'a t = 'a list
val null = List.null
val empty = []
val cons = op::
val hd = List.hd
val tl = List.tl
end
structure LazyList : MYLIST =
struct
datatype 'a t = Nil | Cons of 'a * (unit -> 'a t)
val empty = Nil
fun null Nil = true
| null _ = false
fun cons (x, xs) = Cons (x, fn () => xs)
fun hd Nil = raise Empty
| hd (Cons (x, _)) = x
fun tl Nil = raise Empty
| tl (Cons (_, f)) = f ()
end
structure ConcatList : MYLIST =
struct
datatype 'a t = Nil | Singleton of 'a | Concat of 'a t * 'a t
val empty = Nil
fun null Nil = true
| null (Singleton _) = false
| null (Concat (xs, ys)) = null xs andalso null ys
fun cons (x, xs) = Concat (Singleton x, xs)
fun hd Nil = raise Empty
| hd (Singleton x) = x
| hd (Concat (xs, ys)) = hd xs
fun tl Nil = raise Empty
| tl (Singleton x) = Nil
| tl (Concat (xs, ys)) = (* exercise *)
end
signature MYLISTCOMB =
sig
type 'a t
val length : 'a liste -> int
val map : ('a -> 'b) -> 'a liste -> 'b liste
val foldl : ('a * 'b -> 'b) -> 'b -> 'a liste -> 'b
val append : 'a liste * 'a liste -> 'a liste
val concat : 'a liste liste -> 'a liste
val sort : ('a * 'a -> order) -> 'a t -> 'a t
end
functor ListComb (X : MYLIST) : MYLISTCOMB =
struct
type 'a t = 'a X.t
open X
fun length xs =
if null xs then 0
else 1 + length (tl xs)
fun map f xs =
if null xs then empty
else cons(f (hd xs), map f (tl xs))
fun foldl f e xs =
if null xs then e
else foldl f (f (hd xs, e)) (tl xs)
fun append (xs, ys) =
if null xs then ys
else cons (hd xs, append (tl xs, ys))
fun concat xs =
if null xs then empty
else append (hd xs, concat (tl xs))
fun sort cmp xs = (* exercise *)
end
structure RegularListComb = ListComb (RegularList)
structure LazyListComb = ListComb (LazyList)
structure ConcatListComb = ListComb (ConcatList)
Not sure I fully understand your question. Obviously, functors are useful for defining modular abstractions that (1) are polymorphic, (2) require a whole set of operations over their type parameters, and (3) provide types as part of their result (in particular, abstract types), and (4) provide an entire set of operations.
Note that your example doesn't make use of (3), which probably is the most interesting aspect of functors. Imagine, for example, implementing an abstract matrix type that you want to parameterise over the vector type it is based on.
One specific characteristic of ML functors -- as well as of core-language polymorphic functions -- is that they are parametric. Parametricity is a semantic property saying that evaluation (of polymorphic code) is oblivious to the concrete type(s) it is instantiated with. That is an important property, as it implies all kinds of semantic goodness. In particular, it provides very strong abstraction and reasoning principles (see e.g. Wadler's "Theorem's for free!", or the brief explanation I gave in reply to another question). It also is the basis for type-erasing compilation (i.e., no types are needed at runtime).
Parametricity implies that a single functor cannot have different implementations for different types -- which seems to be what you are asking about. But of course, you are free to write multiple functors that make different semantic/complexity assumptions about their parameters.
Hope that kind of answers your question.
Here is a number of useful examples of SML functors. They are made on the following premise: If you can do one set of things, this enables you to do another set of things.
A functor for sets: If you can compare elements, you can create sets using balanced data structures (e.g. binary search trees or other kinds of trees).
signature SET =
sig
type elem
type set
val empty : set
val singleton : elem -> set
val union : set -> set -> set
val intersect : set -> set -> set
end
signature ORD =
sig
type t
val compare : t * t -> order
end
functor BalancedSetFunctor(structure Cmp : ORD) :> SET =
struct
type elem = Cmp.t
type set = ...
val empty = ...
fun singleton x = ...
fun union s1 s2 = ...
fun intersect s1 s2 = ...
end
A functor for iteration: For any kind of collection of things (e.g. lists), if you can iterate them, you can automatically fold them. You can also create different structures for different ways to fold across the same datatype (e.g. pre-order, in-order and post-order traversal of trees).
signature ITERABLE =
sig
type elem
type collection
val next : collection -> (elem * collection) option
end
signature FOLD =
sig
type elem
type collection
val fold : (elem * 'b -> 'b) -> 'b -> collection -> 'b
end
functor FoldFunctor(Iter : ITERABLE) :> FOLD =
struct
type elem = Iter.elem
type collection = Iter.collection
fun fold f e xs =
case Iter.next xs of
NONE => e
| SOME (x, xs') => fold f (f (x, e)) xs'
end
Functors are "lifters" - they lift (this verb is standard FP terminology): for a given set of types and values, they let you create a new set of types and values on top of them.
All the modules conforming to the required module interface can "benefit" from the functor, but they don't lose their special abilities, if by abilities you mean the implementation specific advantages.
Your very example, for instance, works well to demonstrate my point: concatenation lists have a very fast concat operator, as you wrote, and when lifted with the functor, this 'ability' doesn't vanish. It's still there and perhaps even used by the functor code. So in this example the functor code actually benefit from the list implementation, without knowing it. That's a very powerful concept.
On the other hand, since modules have to fit an interface when lifted by a functor, the superfluous values and types are lost in the process, which can be annoying. Still, depending on the ML dialect, this restriction might be somewhat relaxed.