The reflection
package offers a class
class Reifies s a | s -> a where
reflect :: proxy s -> a
and a function
reify :: a -> (forall s . Reifies s a => Proxy s -> r) -> r
Given only these, one could mess things up rather badly by giving, for example, the instance
instance Reifies s Int where
reflect _ = 0
This would be bad because, for instance,
reify (1 :: Int) $ \p -> reflect p
could legitimately produce either 1 (via the usual reflection process) or 0 (by specializing the passed function before applying reify
).
In reality, this particular exploit seems to be blocked by the inclusion of a few Reifies
instances in Data.Reflection
. The evil instance I described will be rejected as overlapping. If overlapping instances are enabled, I believe the specialization may be blocked by the uncertainty overlapping brings.
Still, I'm wondering if there's some way to expose this with a shady instance, perhaps with the help of GADTs or some such.
Harms of reflection One of the biggest risks of reflection, in our view, is failure to reflect. “A doctor who appears to be failing to reflect properly could be criticised for lacking insight, making an employer or regulator consider them a risk to patients.” 4 Learning without reflection is a waste.
We chose Reflection-Based Safety because if there’s one thing that the safety profession seems to be lacking these days it’s a healthy dose of self-reflection. We often are so focused on external factors – hazards, compliance, getting people to follow the rules, getting management commitment to safety.
“A doctor who appears to be failing to reflect properly could be criticised for lacking insight, making an employer or regulator consider them a risk to patients.” 4 Learning without reflection is a waste. Reflection without learning is dangerous The products of reflection, for example, a written portfolio, need to be professional at all times.
Cottrell (2010) pointed out that the reflective process is challenging. This is because we do not always like to discover the truth about ourselves and the things we most need to know can be the hardest to hear. It takes time and practice for anyone to develop good reflective skills.
I tentatively say it doesn't risk incoherence. After some tinkering, the best way I could come up with to hijack reflect
used INCOHERENT
, which is unsurprisingly sufficient to yield incoherence:
{-# LANGUAGE
TypeFamilies, FlexibleInstances, MultiParamTypeClasses,
ScopedTypeVariables #-}
import Data.Constraint
import Data.Proxy
import Data.Reflection
instance {-# INCOHERENT #-} Reifies (s :: *) Int where
reflect _ = 0
reflectThis :: forall (s :: *). Dict (Reifies s Int)
reflectThis = Dict
-- prints 0
main = print $
reify (1 :: Int) $ \(p :: Proxy s) ->
case reflectThis :: Dict (Reifies s Int) of
Dict -> reflect p
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With