I saw this snippet at the devlog of omegagb:
data ExecutionAST result where
Return :: result -> ExecutionAST result
Bind :: (ExecutionAST oldres) -> (oldres -> ExecutionAST result) ->
ExecutionAST result
WriteRegister :: M_Register -> Word8 -> ExecutionAST ()
ReadRegister :: M_Register -> ExecutionAST Word8
WriteRegister2 :: M_Register2 -> Word16 -> ExecutionAST ()
ReadRegister2 :: M_Register2 -> ExecutionAST Word16
WriteMemory :: Word16 -> Word8 -> ExecutionAST ()
ReadMemory :: Word16 -> ExecutionAST Word8
What does the data ... where mean? I thought the keyword data is used to define a new type.
It defines a new type, the syntax is called generalized algebraic data type.
It is more general than the normal syntax. You can write any normal type definition (ADT) using GADTs:
can be written as:
But you can also restrict what is on right hand side:
which is not possible with a normal ADT declaration.
For more, check Haskell wiki or this video.
The reason is type safety.
ExecutionAST tis supposed to be type of statements returningt. If you write a normal ADTthen
ReadMemory 5will be a polymorphic value of typeExecutionAST t, instead of monomorphicExecutionAST Word8, and this will type check:That statement should read memory from location 1 and write to register
x. However, reading from memory gives 8-bit words, and writing toxrequires 16-bit words. By using a GADT, you can be sure this won’t compile. Compile-time errors are better than run-time errors.GADTs also include existential types. If you tried to write bind this way:
then it won’t compile since “oldres” is not in scope, you have to write:
If you are confused, check the linked video for simpler, related example.