
Thanks for pointing that out.
I haven't been seriously dealing with the monad laws as the code is not even working yet.
But I guess it should be able to adjust the definition to fit the monad laws.
Say, with current definition we have
return 1 >>= return
===
WH ([],1) >>= \x->WH ([],x)
===
WH ([1],1)
But if we change the definition of >>= to
WH (h,a) >>= fm = WH (h1++if a == b then coerceHistory h else coerceHistory (a:h),b) where ...
then
return 1 >>= return
===
WH ([],1)
while
return 1 >>= return.(+2)
===
WH ([1],3)
Of course this may break in other cases.
The reason is that (apart from reducing explicit recording) I have used the Maybe monad extensively
to express "computation that may fail" in existing code, and in the end I would like something which not only
handles the possible failure also records history based on this WithHistory monad.
在 2018-11-19 01:34:33,"Dan Burton"
newtype WithHistory b = WH ([b], b)
and just discard the older steps when the input and output are of different types.
newtype WithHistory b = WH ([b], b) deriving (Show,Eq) instance Monad WithHistory where return b = WH ([], b) (>>=) :: forall a b. WithHistory a -> (a -> WithHistory b) -> WithHistory b WH (h,a) >>= fm = WH (h1++coerceHistory (a:h),b) where WH (h1, b) = fm a class CoerceHistory a b where coerceHistory :: [a] -> [b] instance CoerceHistory a a where coerceHistory = id instance CoerceHistory a b where coerceHistory _ = [] I have got the coerceHistory function to (appear to) work in GHCi *Main> coerceHistory [2::Int] :: [Int] [2] *Main> coerceHistory "c" :: [Int] [] But the Monad instanciation does not really work. GHC(7.6.3) hints for -XIncoherentInstances, which when enabled seems to force the (>>=) to always use the instance of coerceHistory returning []
The second approach is to use [Dynamic] for steps, i.e.,
newtype WithHistory b = WH ([Dynamic], b) instance Monad WithHistory where return b = WH ([], b) WH (h,a) >>= fm = WH (h1++forceDynList a++h, b) where WH (h1, b) = fm a and presumably
class ForceDynList a where forceDynList :: a -> [Dynamic] instance (Typeable a) => ForceDynList a where forceDynList x = [toDyn x] instance ForceDynList a where forceDynList x = [] which is far from correct with error "Duplicate instance declarations"
Thanks! Ducis -- ----------------------------- At 2018-11-18 20:00:01, haskell-cafe-request@haskell.org wrote:
Send Haskell-Cafe mailing list submissions to haskell-cafe@haskell.org
To subscribe or unsubscribe via the World Wide Web, visit http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe or, via email, send a message with subject or body 'help' to haskell-cafe-request@haskell.org
You can reach the person managing the list at haskell-cafe-owner@haskell.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of Haskell-Cafe digest..."
Today's Topics:
1. Timing out a pure evaluation of an expression I did not write myself (Ryan Reich) 2. Re: Timing out a pure evaluation of an expression I did not write myself (Daniel Díaz Casanueva) 3. Re: Timing out a pure evaluation of an expression I did not write myself (Daniel Díaz Casanueva) 4. Re: Timing out a pure evaluation of an expression I did not write myself (Ryan Reich) 5. Specialize a function on types of arguments? (ducis) 6. Re: Specialize a function on types of arguments? (Anthony Clayden) 7. Re: Timing out a pure evaluation of an expression I did not write myself (arjenvanweelden@gmail.com) 8. external git dependency source in .cabal (Fabien R)
----------------------------------------------------------------------
Message: 1 Date: Sat, 17 Nov 2018 15:21:53 -0800 From: Ryan Reich
To: haskell-cafe Subject: [Haskell-cafe] Timing out a pure evaluation of an expression I did not write myself Message-ID: Content-Type: text/plain; charset="utf-8" I want to time out a pure computation. My experience, and that described in various previous questions here and elsewhere (the best of which is https://mail.haskell.org/pipermail/haskell-cafe/2011-February/088820.html), is that this doesn't always work: for instance,
timeout 1 $ evaluate $ let x = 0 : x in last x
does not time out because, apparently, the fact that the expression evaluates in constant space (i.e. never allocates) means that it never yields to the timeout monitor thread that would kill it.
The solution that is described in the other iterations is to embed checkpoints in the expression that do allocate, giving the RTS a chance to switch contexts. However, in my application, the expression is /arbitrary/ and I do not have the freedom to inject alterations into it. (Don't argue this point, please. The expression is arbitrary.)
How can I time out a tight loop like the above? Clearly, it can be done, because I can, say, alt-tab over to another terminal and kill the process, which exploits the operating system's more aggressively pre-emptive scheduling. Is there a solution using bound threads, say 'forkOS' instead of 'forkIO' in the implementation of 'timeout'? Unix signals? Some FFI-based workaround? Etc. Keep in mind that notwithstanding that comment, I don't actually want to kill the whole process, but just the one evaluation.
Thanks in advance, Ryan Reich