简体   繁体   中英

`f :: a -> IO ()` evaluation in do thread : Haskell

This is a repost of my previous question(deleted by myself) since I considered it would be adequate to change the focus by presenting the sample code below.

Basically, I try to implement a Functor that takes a function such as id , \a -> a + 1 or even print .

So the function type can be

f:: a -> b

f:: a -> IO ()

module Main where

import Control.Monad.Primitive (PrimMonad (PrimState))
import qualified Data.Vector.Mutable as M
import System.IO.Error (isDoesNotExistErrorType)

main :: IO ()
main = do
  let ioA = io (5 :: Int)
  let f = print
  --  f = \a -> a + 1
  let ioB = someFunctor f ioA

  ioB

  print "done"

data R a = R
  { val :: M.MVector (PrimState IO) a
  }

io :: a -> IO (R a)
io = \a -> do
  val <- M.new 1
  M.write val 0 a
  return $ R val

_val :: R a -> IO a
_val = \ra -> M.read (val ra) 0

someFunctor :: Show a => (a -> b) -> IO (R a) -> IO (R b)
someFunctor = \f -> \ioA -> do
  print "-- someFunctor"

  val <- ioA >>= _val
  print val --works    5
  let ioB = io $ f val

  --here, I want to actually `print val` when `f == print`
  return $ f val

  ioB

Output

"-- someFunctor"
5
"done"

The current sample code woks without errors, and what I want to achieve is to evaluate

f val

where

  1. f val is the value wrapped into the new container ioB : io $ f val

  2. However, due to the lazy-evaluation strategy of Haskell or some other reason, when f == print , this is not actually performed, so the val is not printed against my expectation.

  3. So far, I did return $ f val , but this does not work unlike the working print val .

  4. Just f val in do thread doesn't go well because f can be id and in that case, it's not IO type. Type mismatch. The compiler smartly generates an error here thanksfully.

  5. So, my question is what is the generic way to implement f val to be evaluated when f == print f:: a -> IO () ?

If you want to do IO , you have to admit you're doing IO .

someFunctor :: Show a => (a -> IO b) -> IO (R a) -> IO (R b)
someFunctor = \f -> \ioA -> do
    {- ... -}
    b <- f val
    io b

You can lift non- IO functions to IO ones with return , as in

someFunctor (return . id)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM