1
votes

I have a little problem with Data Types in Haskell, I think I should post first some code to help to understand the problem

helper ::  (MonadMask a, MonadIO a, Functor a) => Expr -> String ->  a (Either InterpreterError Int)
helper x y = ( getEval ( mkCodeString x y ) )

-- Creates Code String
mkCodeString :: (Show a) => a -> String -> String
mkCodeString x y = unpack (replace (pack "Const ") (pack "") (replace (pack "\"") (pack "") (replace  (pack "Add") (pack y) (pack (show x) ) ) ) ) 

-- Calculates String
getEval :: (MonadMask m, MonadIO m, Functor m) => [Char] -> m (Either InterpreterError Int)
getEval str = (runInterpreter (setImports ["Prelude"] >> interpret str (as ::Int)))

-- | A test expression.
testexpression1 :: Expr
testexpression1 = 3 + (4 + 5)

-- | A test expression.
testexpression2 :: Expr
testexpression2 = (3 + 4) + 5

-- | A test expression.
testexpression3 :: Expr
testexpression3 = 2 + 5 + 5

I use the helper Function like this "helper testexpression3 "(+)" and it returns me the value "Right 12" with the typ "Either InterpreterError Int", but I only want to have the "Int" value "12"

I tried the function -> "getValue (Right x) = x" but I dont get that Int value. After some time of testing I think it is a problem with the Monads I've used.

If I test the typ of the helper function like this: ":t (helper testexpression1 "(+)")" I'll get that: "(... :: (Functor a, MonadIO a, MonadMask a) => a (Either InterpreterError Int)"

How can I make something like that working: write "getValue (helper testexpression1 "(+)")" and get "12" :: Int

I'll know that the code makes no sence, but its a homework and I wanted to try some things with haskell.Hope you have some more Ideas than I am.

And Sorry for my bad English, I have began to learn English, but I am just starting and Thank you for every Idea and everything.

Edit, here is what was missing on code:

import Test.HUnit (runTestTT,Test(TestLabel,TestList),(~?))
import Data.Function (on)
import Language.Haskell.Interpreter -- Hint package 
import Data.Text
import Data.Text.Encoding
import Data.ByteString (ByteString)
import Control.Monad.Catch

-- | A very simple data type for expressions.
data Expr = Const Int | Add Expr Expr deriving Show

-- | 'Expression' is an instance of 'Num'. You will get warnings because
--   many required methods are not implemented.
instance Num Expr where
    fromInteger = Const . fromInteger
    (+) = Add

-- | Equality of 'Expr's modulo associativity.
instance Eq Expr where
    (==) x1 x2 = True --(helper x1 "(+)") ==  (helper x2 "(+)") && (helper x1 "(*)") == (helper x2 "(*)")  

That functions are also in the file ... everything else I have in my file are some Testcases I have created for me.

1
Your code is very difficult to understand, mostly because you use functions and data types (MonadMask, Expr, runInterpreter) that are not shown. Please post the minimal amount of code that compiles and demonstrates the problem you're having. - cdk
You tried to patten match on the result of helper as if it was Either a b, but it is (MonadMask m, MonadIO m, Functor m) => m (Either a b), so you have to unwrap the monad layer before you can pattern match on Left or Right constructors. - cdk
You could do something like this in main: main = do { result <- helper testexpression1 "(+)"; case result of { Right x -> print x; Left err -> putStrLn "There was an error!" } }, but feel free to reformat that into multiple lines. The short answer is that you're restricted to being inside IO at some point, and you can't escape from IO in Haskell (except for unsafePerformIO, which you might guess by its name is not safe for every day use, it causes very strange problems and exists mainly for low level operations in advanced code, do not use it unless you know what you're doing!). - bheklilr
Ohh that was fast :D Thank you. Now I have updated the code above,but you have allready answered my question. Ok, lets look what it means to unwarp the monad :D Thank you - de-loke
@user3803077 Some monads are just a data structure, like Maybe and Either. In fact, most (if not all) monads that are not built on top of IO are simply that, a data structure. Executing a "monadic" action is just building up a data structure for that monad. IO is a special monad, it's one that you don't have access to its constructors and it truly is impure, you can get different values out each time you run it (e.g. reading from a file). Any monad that is just a data structure can usually be "unwrapped" to get a final result, meaning it's just deconstructed to get some value out. - bheklilr

1 Answers

1
votes

helper textExpr "(+)" is not of type Either InterpreterError Int it is of type (MonadMask a, MonadIO a, Functor a) => a (Either InterpreterError Int). This later tyoe can be treated as if it was IO (Either InterpreterError Int) for our purposes.

In general something of type IO a (e.g. IO (Either InterpreterError Int)) doesn't contain, in the strictest sense, a value of type a, so you can't just extract a value willy-nilly. Something of type IO a is an action, that when performed, will produce a value of type a. Haskell only performs one action, the one called main. That said, it allows us to easily build larger actions out of smaller actions.

main = helper textExpr "(+)" >>= print

That operator there (>>=) is a monadic bind. For more information about monads in general, see You Could Have Invented Monads!. For an idea of how the IO Monad might be constructed see Free Monads for Less (Part 3 of 3): Yielding IO (under "Who Needs the RealWorld?") or Idris' implementation of IO -- but keep in mind that the IO Monad is opaque and abstract in Haskell; don't expect to be able to get an a value from an IO a value unless you are writing main (an application).