Last.fm Blog: Library and streaming services outage
blog.last.fm2 pointsby Martijn0 comments
data Answer = AnswerBool Bool | AnswerInt Int | ...
and then processing the answer (through pattern matching) would have to discard any answer it didn't like, which is awkward. Or I would have had to use a type class to keep everything type-safe which would have resulted in more complicated type signatures throughout the code. \(target1, target2) -> ...
rather than a normal list: \[target1, target2] -> ...
which in this case results in a pattern match exception if you pass it a list of any length other than 2. data Question a where
AskKeepHand :: Question Bool
AskTarget :: [EntityRef] -> Question EntityRef
...
This allows me to write cards that ask questions and later on plug in various interpreters of these questions (command line interface, JSON webserver, AI, test framework). type ObjectRef ty = (ZoneRef ty, Id)
lookupObject :: ObjectRef ty -> Magic (ObjectOfType ty)
Most functions that take object references as an argument like to constrain the type of the object referenced, and using a GADT allows them to do so. For example, dealing damage to an object (creature or planeswalker): data SimpleOneShotEffect = DamageObject Object (ObjectRef TyPermanent) Int ...
3) Type TargetList models zero or more targets a spell on the stack can target. Even though in essence it is just a list of targets, it is a GADT so that it can have a "return type" which is re-evaluated when one of more of the targets change (for example, by a card like Redirect or Reverberate). forever :: Monad m => m a -> m b
Since it never returns a value, the resulting monadic action can be polymorphic in its return type. identity = Invertible id id
But to answer your question anyway, this is the responsible line of code: https://github.com/marekdlugos/TakeMeAsIntern/blob/master/as...