Porting Haskell list comprehensions to Standard ML
Feedback:

The Haskell pyths is not very efficient, and it contains duplicate answers.

fun instead of val/val rec is syntactic sugar for function declarations.

Instead of generateIntsUpTo n, use List.tabulate (n, fn i =&gt; i+1).

Using rev to achieve a tail-recursive function can be a good choice. Neither SML/NJ's or Moscow ML's List.tabulate is tail-recursive, though. If you're worrying about performance here, consider the fact that you don't actually need to store these numbers in lists -- this is purely a convenience so that you can use list comprehensions to iterate their combinations.


Pythagorean triples in Standard ML

I wanted to do it using the minimum amount of custom code.

To achieve the same efficiency as the Haskell pyths and use the minimum amount of custom code, here is one version that uses List.filter, List.concat and List.tabulate:
fun isPythTriple (x, y, z) = x*x + y*y = z*z
fun tab1 n f = List.tabulate (n, fn i =&gt; f (i+1))
fun pyths n =
    List.filter isPythTriple (
      List.concat (tab1 n (fn x =&gt;
      List.concat (tab1 n (fn y =&gt;
                   tab1 n (fn z =&gt; (x,y,z)))))))

This takes several seconds for pyths 10; there really is not reason to generate O(n³) list elements when the solution subset is so sparse.

I have been thinking on write my own recursive functions

Writing your own helper functions is really not something that should be avoided. Generally, using library functions is good, but Standard ML's library is somewhat limited. For example, List.tabulate can't iterate a range of numbers without generating the list in memory. And as you're hinting at, the multiple nested foldrs does not make the code particularly readable.
You could for example combine List.tabulate and List.filter to reduce memory consumption:
fun tabfilter (from, to, f) =
    if from &gt; to then [] else
      case f from of
           SOME value =&gt; value :: tabfilter (from+1, to, f)
         | NONE       =&gt;          tabfilter (from+1, to, f)

fun isPythTriple (x, y, z) = x*x + y*y = z*z

fun pyths n =
    List.concat (tabfilter (1, n, fn x =&gt;
      SOME (List.concat (tabfilter (1, n, fn y =&gt;
        SOME (tabfilter (1, n, fn z =&gt; Option.filter isPythTriple (x, y, z))))))))

This runs orders of magnitude faster. Still, it is a little convoluted.
A plain recursive version:
fun isPythTriple (x, y, z) = x*x + y*y = z*z
fun pyths n =
    let fun loop (0, _, _) = []
          | loop (x, 0, _) = loop (x-1, n, n)
          | loop (x, y, 0) = loop (x, y-1, n)
          | loop (t as (x, y, z)) =
            if isPythTriple t then t :: loop (x,y,z-1) else loop (x,y,z-1)
    in rev (loop (n, n, n)) end

And a tail-recursive variant of the same:
fun isPythTriple x y z = x*x + y*y = z*z
fun pyths n =
    let fun loop 0 _ _ res = res
          | loop x 0 _ res = loop (x-1) n n res
          | loop x y 0 res = loop x (y-1) n res
          | loop x y z res =
            let val res' = if isPythTriple x y z
                           then (x,y,z) :: res
                           else res
            in loop x y (z-1) res'
            end
    in loop n n n [] end