I suppose it depends how you define the free module over `S`

-- I think the recommended way is using `CombinatorialFreeModule`

, although while trying to do what you want, I did get a number of errors saying that it is "still using old coercion framework", whatever that means . . .

In any case, I think I was able to do something like what you want, as long as your basis set is finite. Let me know if it works for you:

```
sage: a = (1,1,1)
sage: b = (1,3,2)
sage: c = (2,1,2)
sage: F = CombinatorialFreeModule(ZZ,[a,b,c])
sage: f = lambda x: sum(x)*F.basis()[x]
sage: f(a)
3*B[(1, 1, 1)]
sage: f(b)
6*B[(1, 3, 2)]
sage: f(c)
5*B[(2, 1, 2)]
sage: phi = F.hom([f(x) for x in [a,b,c]], F)
sage: phi.on_basis()
[3*B[(1, 1, 1)], 6*B[(1, 3, 2)], 5*B[(2, 1, 2)]]
```

Note, in particular, that it's a little tricky to get the elements `a, b, c`

as elements of `F`

. The method `F.basis()`

gives the basis as a sage finite family, and you recover the element corresponding to `a`

, for example, as if it were the key in a python dictionary: `F.basis()[a]`

. Such a convoluted approach would not be necessary if coercion was working correctly.

Some further examples of `.hom()`

are given (for rings) at the Homomorphisms of rings manual page.