"0<" is known as a redirection symbol for standard input (as far as I understand). Now, since the standard input is a keyboard, shouldn't patch command read from the keyboard and not from file.diff? How does the above command work?
No. Standard input is connected to the keyboard (or more accurately to the 'tty' device through which the OS provides keyboard input). At any time, the connection can be closed and something else opened in its place – the term "standard input" refers to the specific connection "slot" and not to where it goes. (Which is why it is called "standard input" and not "keyboard input".)
The numbers are not just shell syntax; they represent how programs themselves work with open files. Within each process, every "open file" is represented by a number (the file descriptor, or the handle as Windows calls it) and all read/write calls work on that number. By standard convention, whichever open file is assigned the file descriptor 0 is the "standard input".
If you start the program from a terminal, then the terminal's "tty" is pre-opened as FD 0 – or rather, inherited from the shell where it was already open – and is therefore the program's stdin. (Same for 1 being stdout and 2 being stderr.) Then the 'diff' program will itself need to open some files, so it will call open("fileA", ...) and fileA will be open as FD 3 and so on.
But just like the program can close any file it has opened itself (e.g. it can close fileA by doing close(3)), it can also do close(0) to close its stdin and open something else in its place; as long as the newly open file receives file descriptor 0 it is by definition "standard input".
The shell can do the same right before it starts the program. Using <file.diff or 0<file.diff means the shell will close its original stdin file descriptor with close(0) and open the file open("file.diff") as the new FD 0 which then becomes the new stdin, to be inherited by the 'diff' program. (This happens in the child process that the shell creates for starting 'diff', without affecting the main shell process.) Now, when diff calls read(0, …) it will read from the file.
Side notes:
Usually open() uses the lowest-available file descriptor, e.g. if 0 was just closed, then the next open()ed file will be 0 again. If more precise control is needed, dup2() can be used to choose a specific FD.
It is possible to redirect any file descriptor, e.g. 5>file.txt will give the program a pre-opened FD 5 corresponding to that file, but that's only useful if the program expects to receive one; otherwise it'll remain open but unused. (Some programs have options like gpg --status-fd= which can be used to pass additional FDs.)
Windows has similar concepts and its cmd.exe even has the same 2> syntax, but Windows file handles aren't actually numbered starting from 0 (they're memory pointers), so cmd.exe only implements 0/1/2 and translates them to Windows-style standard handles. (Meanwhile PowerShell is its own strange world.)
Similar to the example David Anderson gave, ls -l /proc/self/fd – on Linux only – can be used to inspect its own file descriptors, or ls -l /proc/<pid>/fd for any other process. For example:
$ ls -l /proc/self/fd
total 0
lrwx------ 1 users 64 Feb 24 14:38 0 -> /dev/pts/4
lrwx------ 1 users 64 Feb 24 14:38 1 -> /dev/pts/4
lrwx------ 1 users 64 Feb 24 14:38 2 -> /dev/pts/4
lr-x------ 1 users 64 Feb 24 14:38 3 -> /proc/833587/fd/
Here file descriptors 0 (stdin), 1 (stdout), 2 (stderr) are currently connected to the terminal (all inherited from the shell), while 3 was opened by 'ls' itself and is of course the directory being listed. If you redirect stdin using <, you get:
$ ls -l /proc/self/fd < ~/test.c
total 0
lr-x------ 1 users 64 Feb 24 14:39 0 -> /home/grawity/test.c
lrwx------ 1 users 64 Feb 24 14:39 1 -> /dev/pts/4
lrwx------ 1 users 64 Feb 24 14:39 2 -> /dev/pts/4
lr-x------ 1 users 64 Feb 24 14:39 3 -> /proc/833693/fd/
And the same with a few useless file descriptors given to the program:
$ ls -l /proc/self/fd 5< ~/test.c 9> /dev/null
total 0
lrwx------ 1 users 64 Feb 24 14:41 0 -> /dev/pts/4
lrwx------ 1 users 64 Feb 24 14:41 1 -> /dev/pts/4
lrwx------ 1 users 64 Feb 24 14:41 2 -> /dev/pts/4
lr-x------ 1 users 64 Feb 24 14:41 3 -> /proc/833741/fd/
lr-x------ 1 users 64 Feb 24 14:41 5 -> /home/grawity/test.c
l-wx------ 1 users 64 Feb 24 14:41 9 -> /dev/null