Sign up ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

I understand what dynamic and static type systems are, and what duck typing is. But I don't understand how you can have a static language that supports duck typing. To my understanding only a dynamically typed language can support duck typing.

This answer from StackOverflow explains that "Duck typing is something that is completely orthogonal to static, dynamic, weak, or strong typing." It gives an example from C++ for duck typing in a statically typed language, but I'm not a C++ programmer and I don't understand it.

I'd like an explanation of how it's possible for a static language to support duck typing.

share|improve this question
A Google search for "static duck typing" goes directly to Are there any static duck-typed languages?, which may provide sufficient answers and links to satisfy your curiosity. – Greg Hewgill Aug 11 '14 at 20:25
@GregHewgill See my edit please – Aviv Cohn Aug 11 '14 at 20:25
Do you understand C++ iterators? That is a perfect example. There is no common Iterator base class. Any object which supports operator++ and operator!= (loop increment and bounds check) can function as an iterator, because it walks and quacks like an iterator. This could be one of the many iterator classes defined by the STL, or even a bare pointer. – Snowman Aug 11 '14 at 21:03
I'd give an example in Standard ML but then I'd have to teach you Standard ML. – Doval Aug 11 '14 at 22:34
@Snowman: Iterator requires a lot more than that, namely operator*... – Mooing Duck Aug 11 '14 at 23:48

6 Answers 6

up vote 6 down vote accepted

In my experience, it is simply a language that uses static typing with a Structural Type System. It essentially applies the "walks like a duck, talks like a duck" check at compile type so that the programmer doesn't need to provide annotations to specifically sub-type things.

This has a very large benefit when you're trying to glue two (or more) libraries together. With a nominative type system, if you had some interface in one library and an object in the other, they don't know about one another and can't sub-type - even if the object satisfies the interface's requirements. Structural typing makes that okay.

Making the language static just means that the compiler does that check at compile time, giving you an error early (and clearly) when that object doesn't really satisfy the interface.

There are a few esoteric languages that do this, but most structurally typed languages are also dynamically typed and almost all nominative typed languages are also statically typed.

share|improve this answer
Golang is an interesting example of a not-too-esoteric language that works with static duck typing. Here is an example showcasing static duck typing. Yes, “structural typing” is a better term. – amon Aug 11 '14 at 20:55
@amon - ah, you're right. I had forgotten since I've not spent enough time with Go (and Swift, and some other recent ones). – Telastyn Aug 11 '14 at 20:57

The usual meaning of such a term is just structural typing.

In structurally typed systems, things have a static type. However that type is based on the actual structure of the type rather than any particular type name.

For example, let's say we have the Python code

def foo(bar):

Now it's not clear what the type of bar is, but whatever it is we know

  • It has a method baz which takes no arguments
  • It has a method quux which takes 1 integer argument

Now in a structural type system we could assign foo a type

foo : forall a b. r{baz : () -> a, quux : (int) -> b} -> Void

where that funny r thing means

Any type r which the methods ...

Many languages implement some subset of structurally typed features, C++ for example implements "structural typing" via templates. However this is a slightly adhoc approach.

Other languages implement row-types. These are just structurally typed records/structs! Types where we can say something like "we want a record with at least the fields ...". I believe purescript implements these.

Go has something like structural types with it's "implicit interfaces". These are just interfaces that a type implements automagically. However this isn't full structural types since it doesn't allow for a structural type to be handled parametrically, that is there's no way to say something like

foo :: r{a : int} -> w{a : int} -> r
foo r w = w -- Type error!!

Since everything is "upcasted" to an interface, rather than merely treated opaquely.

There's been some talk of adding these to Haskell view -XOverloadedRecordFields, but I'm not aware of any real progress on structural typing in it's full generality.

share|improve this answer
I'm not sure whether C++ templates can be called a structural type system (I think I've never seen it referred to as such). There's not really any type system that could be structural, it just substitutes the types and sees if that monomorphized code is valid. – delnan Aug 11 '14 at 20:35
@delnan This is what I meant when I said "adhoc". You can formalize you can view C++ as having inferred and unutterable structural types. – jozefg Aug 11 '14 at 20:37

Do you know Typescript?

It may seem as a simplistic example but here it goes: it's a language that compiles to Javascript. Now, Javascript itself is dynamically and duck typed, but let's just forget about JS for a second.

Typescript supports static typing, meaning that it will check if your types are correct during compilation and spit out warnings if it thinks you may have made an error. (You can follow up the tutorial and it will show you an example of this)

However, even if it supports static typing, it also has the whole JS duck typing thing. You can use var all around the place, omitting the types Typescript adds and the code will compile and run.

So, it's statically typed, but you can go quack-quack, too. It will even check the quack-quack for you if you let it.

Duck typing is for your typing convenience and in some languages for having generics (such as C++). Static typing is for checking the types you have specified during compilation, if you're working on a compiled language.

share|improve this answer
Duck typing/structural typing isn't the same as type inference. – Doval Aug 11 '14 at 21:47
I searched for the difference and you're correct. So, in this case, would Typescript duck typing be the object system? – ArthurChamz Aug 11 '14 at 21:52
Like, if I had polymorphism? – ArthurChamz Aug 11 '14 at 21:52
It's only duck typing if you can substitute any two classes as long as they contain the same methods and types. – Doval Aug 11 '14 at 22:00

Statically typed just means the types are checked at compile time. It's just as easy for a compiler to check that a type has a method with a certain name and signature as it is to check that a type is a part of a specific inheritance hierarchy. The trick is finding a concise way to specify "this argument to this function is any type that has a method with this specific name."

The method I'm most familiar with to accomplish this is using a type class, which is a declaration that basically says, "any type that implements all these functions can be referred to using this name."

Usually you must specifically declare a type to be an instance of a type class, but it doesn't have to be in the same code that the type itself is defined, which means anyone can add their own type class after the fact to types they don't control. That's sort of a compromise to total duck typing, more like, "if it walks like a duck and quacks like a duck, then anyone anywhere can explicitly declare it a duck-like thing, and everyone else can treat it like a duck."

However, it's not that big of a stretch to allow types to be implicitly added to a type class, you just lose a bit of control. As Amon and Jozefg pointed out, the go language has interfaces which basically act like implicitly added type classes.

share|improve this answer
To be clear: Type classes and similar ad-hoc polymorphism usually aren't considered duck typing though, since one must explicitly opt into the type class (even if doing so can happen anywhere in the program) rather than magically having it work after defining just the method. – delnan Aug 11 '14 at 22:01
Yes I agree. It is the closest you usually get in a statically typed language though, and the OP was wondering how that would work. – Karl Bielefeldt Aug 12 '14 at 12:32
@delnan I guess if you really want to be strict about the definitions, they're not the same thing, but I think they're close enough in practice - the key thing to me is that you can apply type classes to pre-existing types at any point. – Doval Aug 12 '14 at 14:59
@Doval That is certainly part of the appeal, but the Pythonista in me and some people I've talked to fights toe and nail against having to write as little boilerplate as instance Blah MyType blahFoo = myFoo. – delnan Aug 12 '14 at 15:35

It doesn't have to be. You can implement 95%ish of duck typing in a static language without that much work. The last 5% you need dependent typing for and it's much more complicated, but that's still a statically typed system. Specifically, the remaining 5% is for conditionally using methods depending on other values, and so having code that still works on data that does not support all of the methods you code conditionally calls.

Here's a chunk of Haskell that I was tinkering with and it implements something very much like static duck typing:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, 
UndecidableInstances, IncoherentInstances, FlexibleContexts #-}

data Addon a b = Addon a b deriving Show

class Plugin a b where
    first :: b -> a
    set   :: a -> b -> b

instance Plugin a a where
    first = id
    set   = const

instance Plugin a (Addon a b) where
    first (Addon a _) = a
    set x (Addon a b) = Addon x b

instance (Plugin a b) => Plugin a (Addon c b)where
    first (Addon _ b) = first b
    set x (Addon a b) = Addon a $ set x b

class Runnable e b c where
    run :: e -> b -> c

instance Plugin a b => Runnable (a -> c) b c where
    run f p = f (first p)

instance (Plugin d b, Runnable e b c) => Runnable (d -> e) b c where
    run f p = run (f $ first p) p

-- The constructor function should NOT be polymorphic *at all*
apply constructor f x = set (constructor $ run f x) x

The Plugin typeclass exists to express containment of types within other types. A type which is an instance of Plugin a b means that it is a type b for which first b can be a value of type a. The two instances given are all that is needed to derive all relevant cases and no further instance declarations are needed.

The Runnable typeclass allows us to chain Plugin instances together and so call a curried multi-argument function on a single datatype so long as it contains a valid component type for each curried argument of the function. Again, no further instance declarations are needed for usage.

The apply function allows us to take a composite type, apply a function to it, and store the result inside that composite type (so long as it already contains a value of the type we wish to store)

Usage would look like so:

data Increment = Inc Integer
data Counter   = Count Integer

counter1 = union (Inc 2) (Count 3)
counter2 = union (Inc 1) (Count 0)

increment (Inc i) (Count c) = i + c

And indeed, this compiles, and we can run it and observe the output:

*Main> apply Count increment counter1
Addon (Inc 2) (Count 5)
*Main> apply Count increment counter2
Addon (Inc 1) (Count 1)

Granted, we had to turn on some rather ugly type extensions, but those extensions are not required to use the library, only to write it. The constructor argument to apply cannot be polymorphic because that would overload the type inference system and it would be unable to make the necessary intermediate type derivations. I was trying to get around that, but I have not made any progress in that direction.

share|improve this answer

If the code shown below compiled in a language that otherwise resembled C, then this fictitious language would presumably exhibit "static" duck typing (according to Wikipedia, at least):

typedef struct s1{
 int a;
 int b;

typedef struct s2{
 int a;
 int b;

s1 thing1;

s2 thing2;
thing2=thing1; //This is where a "real" C compiler would complain
share|improve this answer
Programmers is about conceptual questions and answers are expected to explain things. Throwing code dumps instead of explanation is like copying code from IDE to whiteboard: it may look familiar and even sometimes be understandable, but it feels weird... just weird. Whiteboard doesn't have compiler – gnat Aug 12 '14 at 7:00
I posted a response here and it was deleted. To summarize, I said that I will respect the site guideline, but that I don't agree with it. – user1172763 Aug 12 '14 at 15:24

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.