Getting started with Standard ML
I'm looking for some kind of "ML for beginners" guide - google has led me to some obscure mailing lists or way-over-my-he开发者_如何学Goad texts so far.
The problem is, I have zero functional programming experience so far, and wrapping my head around the concepts has turned out far more difficult than expected. For example, the task I'm trying to do now (yes, university :) ) is do a mapping between two lists (a,b) and (c,d), so that the result is a list of (a,d) from pairs where b = c.
What I would ordinarily do is:
result = []
for each x in list1 do
for each y in list2 do
if x.b == y.c result.add (x.a, y.d)
end
end
But, I can't even get started with implementing something like that in SML. For example, I know I could iterate over lists with nested map f list
's. However, the runtime (SML/NJ) will only accept this for functions that take only list element as parameter. But how do I know what elements to return if I can only operate with one of the two lists at time?
I am in desperate need of a resource that would go over this kind of thing, preferably with big friendly letters and lots of code examples :/
Programming in Standard ML by Prof. Robert Harper of CMU
I have some SML resources bookmarked:
Programming in Standard ML '97: An On-line Tutorial
Elementary Standard ML (Amazon Kindle)
Elements of ML Programming (amazon.com)
For the exercise that you mention, think of a function add
that returns a new list instead of modifying the existing one, and consider how you would implement the exercise recursively in your favorite high-level language, that will be a first step.
You don't need to use map
or any other existing higher-order ML function! These are just shortcuts for experienced programmers. Use pattern-matching and recursion only. But you can look at the implementation of functions such as map
if you seek examples of well-used recursion and pattern-matching.
Recursing over multiple separate lists is messy (but might be what is wanted for this exercise, of course) - it's normally easier to make a single list from them both ("side by side", so in your case each entry would have a pair of integers) and then map or fold over that. I suspect ML will have a function called something like "zip" which should get you started.
Also, not really what you're looking for at the moment, but if you want a good ML book (it's actually a dialect of OCaml, but old enough to not be that different from SML) then look at Cousineau + Mauny. Maybe if you have some time in the holidays. It's a really good book - a bit like SICP, but for ML.
Do you understand what Currying is?
For instance, do you understand the difference between
fun compute(m,b,x):real = m*x+b ;
and
fun linearF (m,b) x : real = m*x+b ;
If you do, can you explain what
val g = linearF(1.0,~1.0) ;
does?
Currying is NOT strictly necessary for solving your problem, but it IS a technique that is used a lot in functional programming. In particular, it gives you a way to use List.map if you want. Here, you want to map over list1 but the function you want to use needs to know about list2 and the result of the computation. This suggests that your code might have the shape
List.map (f [] list2) list1
where f is some appropriately defined Curried function. In general this is a useful trick for providing more information to a function that needs to be a "one argument" function for List.map-like reasons.
Does this help?
Consider this following code of map2, this function does exactly what map does but with two lists.
exception UnequalLengths;
fun map2(f,[],[]) = []
| map2(f,(a::s),(a'::s')) =
(f(a,a'))::(map2(f,s,s'))
| map2(f,s,s') = raise UnequalLengths;
fun plus(x,y) = x + y;
fun concat(s1,s2) = s1 ^ s2;
Now you use it like this:
- map2(plus,[1,2,3],[4,5,6]);
val it = [5,7,9] : int list
- map2(concat,["a","b","c"],["d","e","f"]);
val it = ["ad","be","cf"] : string list
Enjoy XD
精彩评论