I have a function declaration of:
iexec :: Instr -> Config -> Config
iexec (LOADI x) (counter, memory, stack) = (counter 1, memory, x:stack)
with Instr and Config being new Typeclasses. I want this to work like so:
>iexec (LOADI 5) (0, empty, [])
>(1, fromList [], [5])
My issue is that I don't know how to return the fromList of the memory, everything else is working. I tried doing
iexec (LOADI x) (counter, memory, stack) = (counter 1, Map.fromList memory, x:stack)
however I get an error, which varies based on the input, but it basically boils down to I don't know the correct syntax for this functionality, or I cannot access the fromList within a function. Anything to point me in the right direction would be helpful, thank you.
EDIT: As requested:
type Config = (Int, [Val] ,[Val])
where Val
is an Int
.
The error message when just using memory is:
error:
• Variable not in scope: empty :: [Val]
• Perhaps you meant ‘mempty’ (imported from Prelude)
|
9 | main = print (iexec (LOADI 5) (0, empty, []))
CodePudding user response:
If you write a type signature that says you return a list, then you cannot return a map instead. So the answer to the question in the title is "No, you can't do that.".
There are a variety of options for alternative plans. One would be to parameterize your Config
type. Assuming you have imported your favorite map implementation module as M
, that would look like this:
type Config2 f = (Int, f Val, [Val])
iexec2 :: Instr -> Config2 [] -> Config2 (M.Map Int)
iexec2 (LOADI x) (counter, memory, stack) = (counter 1, M.fromList (zip [0..] memory), x:stack)
main = print (iexec2 (LOADI 5) (0, [], []))
Another option would be to just change your Config
type to always be a map:
type Config3 = (Int, M.Map Int Val, [Val])
iexec3 :: Instr -> Config3 -> Config3
iexec3 (LOADI x) (counter, memory, stack) = (counter 1, memory, x:stack)
main = print (iexec3 (LOADI 5) (0, M.empty, []))
There are further options, but I think these two are the cleanest.