Home > Blockchain >  if typeOf f == io then f else return . f in Haskell?
if typeOf f == io then f else return . f in Haskell?

Time:02-08

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:

https://stackoverflow.com/a/71020780/17053359

  •  Tags:  
  • Related