Related to
https://stackoverflow.com/a/71020780/17053359
We can lift non-IO functions : f to IO ones with return, as in
return . f
and now, I want to make this f generic including IO
f :: A -> IO A -- not IO to IO
f :: IO a -> IO a -- (no change, `id` instead of `return`)
in other words:
if typeOf f == io then f
else return . f
What would the code be in Haskell?
EDIT:
console.log(
Object(1)
);
console.log(
Object(Object(1))
);
console.log(
Object(Object(Object(1)))
);
CodePudding user response:
You almost definitely do not actually want to do this. The amount of type level hackery required for this should already scare you away and this is really not how Monads are supposed to be used.
Purely for educational purposes, this is how you could define a function pureish, that behaves just like return if the argument is not of type IO a and just like id if the argument is of type IO a.
type family PureishResult a where
PureishResult (IO a) = a
PureishResult a = a
class Pureish p where
pureish :: p -> IO (PureishResult p)
instance {-# OVERLAPPABLE #-} (PureishResult a ~ a) => Pureish a where
pureish = pure
instance Pureish (IO a) where
pureish = id
Don't say I didn't warn you!
CodePudding user response:
Here's another version of Prophet's answer, without overlapping instances.
{-# language MultiParamTypeClasses, DataKinds, KindSignatures, TypeFamilies, TypeApplications, ScopedTypeVariables, AllowAmbiguousTypes, FlexibleInstances, FlexibleContexts #-}
type family GetUnderlying a where
GetUnderlying (IO a) = a
GetUnderlying a = a
type family IsIO a where
IsIO (IO _) = True
IsIO _ = False
class Pureish (isIO :: Bool) u a where
pureish' :: a -> IO u
instance Pureish False u u where
pureish' = pure
instance Pureish True u (IO u) where
pureish' = id
pureish :: forall a u. (Pureish (IsIO a) u a, u ~ GetUnderlying a) => a -> IO u
pureish = pureish' @(IsIO a)
CodePudding user response:
Answered by myself.
I totally have no idea what's wrong with my question, perhaps my way to ask is not sufficient. At least, I have mentioned idempotency and with my sample snippet JS. but here is my simple solution.
( ) :: (a -> b) -> (b -> c) -> a -> c
( ) = flip (.)
infixl 9
someFunctor :: Show a => (a -> IO b) -> IO (R a) -> IO (R b)
someFunctor = \f -> \ioA -> do
print "-- someFunctor"
val <- ioA >>= _val
b <- (f return join) val
io b
based on the code of my previous Q&A:
