John, That's fine if all you want to do with the module procedure is to use it to initialize the various elements of a derived type, but there are more interesting things one can do with these interfaces, particularly with the operators. As, a fairly trivial example, below is a derived type that defines the date, and then the operator > is defined to compare whether one date is after another date.
MODULE dates
TYPE pdate
INTEGER :: iyr ! - year -
INTEGER :: imn ! - month -
INTEGER :: idy ! - day -
END TYPE pdate
!
INTERFACE OPERATOR(>)
MODULE PROCEDURE gt_pdate
END INTERFACE
!
CONTAINS
FUNCTION gt_pdate(d1,d2)
! Checks whether first date is greater than second date
LOGICAL :: gt_pdate
TYPE(pdate), INTENT(IN) :: d1,d2
!
gt_pdate=.true.
IF (d1%iyr>d2%iyr) THEN
RETURN
ELSE IF (d1%iyr==d2%iyr) THEN
IF (d1%imn>d2%imn) THEN
RETURN
ELSE IF (d1%imn==d2%imn) THEN
IF (d1%idy>d2%idy) RETURN
END IF
END IF
gt_pdate=.false.
RETURN
END FUNCTION gt_pdate
END MODULE dates
Yes, you could just call the required function to give the desired answer, but it can be very handy to use a consistent syntax in a program. For example, imagine a simple test for whether somebody was born in the USA after 9/11. We set an integer idc, which indicates what country the person was born in (in this case based on international dialing codes), while their birthday is stored in dbirth. I think the first test in the programme below that uses the operator is easier to read than the second test that calls the function directly.
PROGRAM p
USE dates
TYPE(pdate) :: d911,dbirth
INTEGER :: idc
d911%iyr=2001
d911%imn=9
d911%idy=11
:
IF ((dbirth>d911).AND.(idc==1)) THEN
PRINT *, 'Born in post-911 USA'
END IF
IF (gt_pdate(dbirth,d911).AND.(idc==1)) THEN
PRINT *, 'Born in post-911 USA'
END IF
END PROGRAM p
Similarly, if we define a procedure for the operators + and -, then it becomes easy to change dates using simple arithmetic syntax rather than having to spell function calls out in full. Granted, one could argue that none of this provides new functionality, but at the cost of 3 lines in the module to define the interface operator, I think it makes for some elegance and simplicity.
One further comment is that there are numerous advantages to packaging functions on derived types with the definitions of those derived types in a single module - hence the need for 'contains', for which you did not see much appeal. The module then becomes very similar to a 'class' of object-oriented languages. Of course, it is easy to work without using these features, but I do think these language features make for easier management of code and structuring of libraries.