Un espace de noms est une chose .Net, commune à de nombreux langages industriels, juste une façon d'organiser les cadres et d'éviter les conflits de noms entre différentes bibliothèques. Vous et moi pouvons définir un type "Foo" et les utiliser tous les deux dans un projet, à condition qu'ils soient dans des espaces de noms différents (par exemple NS1.Foo et NS2.Foo). Les espaces de noms dans .Net contiennent des types.
Un module est une chose F#, il est à peu près analogue à une "classe statique"... c'est une entité qui peut contenir des valeurs et des fonctions let-bound, ainsi que des types (notez que les espaces de noms ne peuvent pas contenir directement des valeurs/fonctions, les espaces de noms peuvent seulement contenir des types, qui eux-mêmes peuvent contenir des valeurs et des fonctions). Les choses à l'intérieur d'un module peuvent être référencées via "NomModule.Chose", qui est la même syntaxe que pour les espaces de noms, mais les modules en F# peuvent également être "ouverts" pour permettre un accès non qualifié, par ex.
open ModuleName
...
Thing // rather than ModuleName.Thing
(EDIT : Les espaces de noms peuvent également être ouverts de manière similaire, mais le fait que les modules puissent contenir des valeurs et des fonctions rend l'ouverture d'un module plus "intéressante", dans la mesure où vous pouvez vous retrouver avec des valeurs et des fonctions, par exemple "cos", qui sont des noms que vous pouvez utiliser directement, alors que dans d'autres langages .Net, vous devriez toujours le qualifier, par exemple "Math.cos").
Si vous tapez du code au "niveau supérieur" dans F#, ce code est implicitement placé dans un module.
J'espère que cela vous aidera, c'est une question assez ouverte :)