DOG proposal

Research: This page describes research about Eiffel, not the actual language specification.


This solution prevents catcalls by prohibiting polymorphic calls to features which are the source of potential catcalls.


A new keyword "cat" (subject to change) is introduced. It can be applied in front of features and type declarations.

  cat f (a: ANY)
      -- Such a feature is called a cat-feature
      l: cat DOG -- Such a type is called a cat-type

Features and types with the "cat" keyword will be referred to from now on as cat-features and cat-types.


In order to be able to redefine argument types of features covariantly and restrict the export status a feature has to be marked with the "cat" keyword. Such features can only be called on types which are declared with the "cat" keyword as well. The semantics of the "cat" keyword is that it is a monomorphic type. This is contrary to ordinary declarations which remain polymorphic. By allowing calls to "cat" features only on monomorphic types the compiler knows exactly which signature to check against. As the type cannot possibly change at runtime because of monomorphism of a cat-type the problem is avoided.

Conformance rules

The conformance stays the same but has one special case more: No type conforms to a cat-type except the same cat-type.

a: A
b: B
ca: cat A
cb: cat B
  -- Conform and therefore valid
a := a
a := b
a := ca
a := cb
b := b
b := cb
ca := ca
cb := cb
  -- Invalid (not all mentioned)
ca := a  -- `a' could be attached to an object of type `B'
ca := b  -- `ca' is monomorphic


See the introduction to examples for information about the classes used but we give enhanced versions for some classes:

class ANIMAL
  cat eat (f: FOOD) do end
  cat sleep do end

This is needed so that the (covariant) redefinition of the argument types of these features or the restriction of the export status is valid.

Cats and dogs


 ca: cat ANIMAL
 c: CAT
 cc: cat CAT
 d: DOG
 cd: cat DOG
 f: FOOD


   -- Invalid calls, both features are marked as cat. (f)
 a.sleep (cf)
   -- In order to be valid their target has to be of cat-type. (f) (cf)



Generics are not that obvious and clear defined in the article. However there is always one save solution.

  ca: cat ANIMAL
  lca: LIST [cat ANIMAL]
  cla: cat LIST [ANIMAL]
  clca: cat LIST [cat ANIMAL]
  cllca: LINKED_LIST [cat ANIMAL]
    -- Invalid:
  lca := la  -- ANIMAL is not cat: The list could contain polymorphic animals
  lca := cla -- This is again because ANIMAL is not cat: Same reason as above.
  clca := lca -- This time it is because we assign to a cat LIST.
  clca := cla -- Here it is again because ANIMAL is not cat.
  clca := llca -- LINKED_LIST is not of cat-type.
    -- Invalid: Attachment to cat-type
  ca := la.item (1) -- The result is not cat-type while the target of the assignment is.
    -- Valid:
  la := lca
  la := cla
  la := clca
  lca := clca
  cla := clca
  lca := llca -- The list can still be used polymorphic
    -- Valid: Attachement to non cat-type
  a := la.item (1)
  a := lca.item (1)
  a := cla.item (1)
  a := clca.item (1)
    -- Valid: Attachement to cat-type
  ca := lca.item (1)
  ca := clca.item (1)


Lacks support for generics

The solution is not suited to prohibit catcalls occurring in the context of generics. If you assumes that each feature of a generic containing the formal as an argument is implicit cat you can only call them on cat lists:

  list: LIST [ANY]
      ll: cat LINKED_LIST [DOG]
      create ll
      ll.extend (create {DOG})
      l: cat LIST [DOG]
      ll: cat LINKED_LIST [DOG]
        -- You cannot write algorithms which fill lists implementation independent.
      -- INVALID: l := ll
        l.extend (create {DOG})

This is because the base type of a generic has two kind of generic features: The ordinary ones like `is_equal' or other special features and then the ones who carry the formal as an argument. The difference is that a feature like `is_equal' changes its signature from LIST [A] to LINKED_LIST [A] but `put' does not.

Programmer needs foresight

This solution requires the programmer to think ahead. If a feature of a library is not marked as "cat" it becomes really difficult to change it later. This is not only because the owner of library is somebody else but also because it would invalidate probably a lot of existing code.


This solution is targeted to ordinary types. However, it can easily be paired with another solution specific for generics. They might even look the same or use partly the same keywords and form a good solution in symbiosis.