Reputation: 97
I'm trying to get the current POSIX time from the system clock using Haskell but get the following error:
• No instance for (Show (IO POSIXTime))
arising from the sixth field of ‘Block’ (type ‘IO POSIXTime’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (Show Block)
|
16 | , nonce :: Maybe Integer } deriving Show
| ^^^^
Here is the code for context:
import Data.Time
import Data.Time.Clock.POSIX
data Transaction = Transaction { from :: String
, to :: String
, value :: Float } deriving Show
data Block = Block { version :: Int
, index :: Int
, transactions :: [Transaction]
, prevBlockHash :: String
, merkleRootHash :: String
, time :: IO POSIXTime
, nonce :: Maybe Integer } deriving Show
genesis :: Block
genesis = Block version index transactions prevBlockHash merkleRootHash time Nothing
where version = 1
index = 0
transactions = []
prevBlockHash = "000000000000000000000000000000000"
merkleRootHash = ""
time = getPOSIXTime
nonce = Nothing
I've referenced a number of solutions to similar questions on stack overflow but haven't been able to get past the error for a few days.
Upvotes: 2
Views: 192
Reputation: 12783
Let's begin by using a illustration of the of the type you have
data Block = Block {
version :: Int
-- removed a few field for illustrative purposes
, time :: IO POSIXTime
, nonce :: Maybe Integer } deriving Show
As was commented IO POSIXTime
is not really a POSIXTime
, but a representation of the action of obtaining a POSIXTime
. And let's change the type to an actual POSIXTime.
data Block = Block {
version :: Int
, time :: POSIXTime
, nonce :: Maybe Integer } deriving Show
Now we can adapt genesis to deal with our new Block: import Data.Time import Data.Time.Clock.POSIX
data Block = Block {
version :: Int
, time :: POSIXTime
, nonce :: Maybe Integer } deriving Show
genesis :: IO Block
genesis =
do
time <- getPOSIXTime
let version = 1
let nonce = Nothing
return (Block version time nonce)
blockTimeAsUTCString :: Block -> String -- No need for IO
blockTimeAsUTCString (Block {time = p}) = show $ posixSecondsToUTCTime p
main :: IO ()
main = ioBlock >>= print >>
ioBlock >>= putStrLn . blockTimeAsUTCString
where ioBlock = genesis
Notice how we moved IO from inside Block to outside and how it plays well with the fact that an Haskell executable is always an IO ()
and blockTimeAsUTCString
shows how the record can be processed without relying on IO.
Upvotes: 8
Reputation: 4640
If you are really stuck with such type signature for Block
I would go on implementing Show (IO POSIXTIme)
:
instance Show (IO POSIXTime) where
show _ = "Time shower"
you might go and make more general Show (IO a)
instance
instance Show (IO a) where
show _ = "I can't Show what is inside this IO monad"
Ultimately,
you can write your own Show
instance of the Block
instead of deriving it:
instance Show Block where
show block = "Block " <> show (version block) <> " .... "
otherwise change Block
type signature to be just POSIXTime
not wrapped in IO
?
Upvotes: -4