LINUX.ORG.RU

История изменений

Исправление quasimoto, (текущая версия) :

Ну и по аналогии с указателем на функцию можно помещать настоящую recvFrom и её имитации в IORef/TVar и везде использовать этот ref/var:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}

import Data.IORef
import System.IO.Unsafe
import Control.Applicative

import Data.ByteString
import Network.Socket hiding ( recvFrom )
import qualified Network.Socket.ByteString as N ( recvFrom )

data RecvFrom = RecvFrom {
  _pointer :: IORef (Socket -> Int -> IO (ByteString, SockAddr))
}

recvFrom :: RecvFrom
recvFrom = unsafePerformIO $ RecvFrom <$> newIORef N.recvFrom 
{-# NOINLINE recvFrom #-}

-- Ya heard 'bout scala?
class Function t r | t -> r where
  apply :: t -> r

instance Function RecvFrom (Socket -> Int -> IO (ByteString, SockAddr)) where
  apply (RecvFrom ref) sock num = readIORef ref >>= \f -> f sock num

mockRecvFrom :: Socket -> Int -> IO (ByteString, SockAddr)
mockRecvFrom _ _ = ...

...

  apply recvFrom socket num -- real recvFrom from Network.Socket.ByteString
  writeIORef (_pointer recvFrom) mockRecvFrom -- change it to mockRecvFrom
  apply recvFrom undefined undefined -- use mock

Исходная версия quasimoto, :

Ну и по аналогии с указателем на функцию можно помещать настоящую recvFrom и её имитации в IORef/TVar и везде использовать этот ref/var:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}

import Data.IORef
import System.IO.Unsafe
import Control.Applicative

import Data.ByteString
import Network.Socket hiding ( recvFrom )
import qualified Network.Socket.ByteString as N ( recvFrom )

data RecvFrom = RecvFrom {
  _pointer :: IORef (Socket -> Int -> IO (ByteString, SockAddr))
}

recvFrom :: RecvFrom
recvFrom = unsafePerformIO $ RecvFrom <$> newIORef N.recvFrom 

-- Ya heard 'bout scala?
class Function t r | t -> r where
  apply :: t -> r

instance Function RecvFrom (Socket -> Int -> IO (ByteString, SockAddr)) where
  apply (RecvFrom ref) sock num = readIORef ref >>= \f -> f sock num

mockRecvFrom :: Socket -> Int -> IO (ByteString, SockAddr)
mockRecvFrom _ _ = ...

...

  apply recvFrom socket num -- real recvFrom from Network.Socket.ByteString
  writeIORef (_pointer recvFrom) mockRecvFrom -- change it to mockRecvFrom
  apply recvFrom undefined undefined -- use mock