2014-07-03 42 views
1

我有在Haskell數據類型有點問題,我想我應該先發布一些代碼來幫助理解這個問題哈斯克爾單子要麼

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 

我使用輔助函數類似這樣的「幫手testexpression3」( +)「,它返回的值爲」Right 12「,典型值爲」Either InterpreterError Int「,但我只希望將」Int「值設置爲」12「

我嘗試了函數 - >」getValue x)= x「但我沒有得到那個Int值 經過一段時間的測試後,我認爲這是我用過的Monads的問題

如果我測試助手函數的類型如下:「:t(helper testexpression1」(+)「)」我會得到:「(... ::(函數a,MonadIO a,MonadMask a )=> A(無論是InterpreterError智力)」

我怎麼能做出這樣的事情工作: 寫 「的getValue(輔助testexpression1 」(+)「)」,並獲得 「12」 ::詮釋

我我知道代碼沒有意義,但它是一個家庭作業,我想用haskell嘗試一些東西。希望你有更多的想法,而不是我。

對不起,因爲我的英語不好,我開始學習英語,但我只是開始,並感謝你的每一個想法和一切。

編輯,這裏是少了什麼的代碼:

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 "(*)") 

,其功能也是在文件中......一切在我的文件,我有是一些測試用例我爲我創造。

+0

您的代碼很難理解,主要是因爲您使用了未顯示的函數和數據類型('MonadMask','Expr','runInterpreter')。請發佈最少量的編譯代碼並演示您遇到的問題。 – cdk

+2

你試圖匹配'helper'的結果,就好像它是''ab'',但它是'(MonadMask m,MonadIO m,Functor m)=> m(任一ab)',所以你必須拆開monad圖層,然後才能在「Left」或「Right」構造函數上進行模式匹配。 – cdk

+2

你可以在'main'中做這樣的事情:'main = do {result < - helper testexpression1「(+)」;個案結果{Right x - > print x;左犯錯 - > putStrLn「出現錯誤!」 }}',但隨時可以將其重新格式化爲多行。簡單的答案是,你被限制在某個時刻處於'IO'內部,並且你不能從Haskell中的'IO'逃脫(除了'unsafePerformIO',你可能會猜到它的名字對每個人都是不安全的它會導致非常奇怪的問題,主要存在於高級代碼中的低級操作,除非您知道自己在做什麼,否則不要使用它)。 – bheklilr

回答

1

helper textExpr "(+)"不是Either InterpreterError Int類型(MonadMask a, MonadIO a, Functor a) => a (Either InterpreterError Int)。這個後來的tyoe可以被視爲我們的目的,就好像它是IO (Either InterpreterError Int)

一般而言,IO a(例如IO (Either InterpreterError Int))的某些內容在最嚴格的意義上並不包含a類型的值,因此您不能僅僅提取一個值。 IO a類型的東西是一種動作,執行時會產生類型爲a的值。 Haskell只執行一個動作,一個叫做main。也就是說,它允許我們輕鬆地從較小的動作中構建更大的動作。

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

那裏的那個運算符(>>=)是一個monadic綁定。有關一般monads的更多信息,請參閱You Could Have Invented Monads!。關於如何構建IO Monad的想法,請參閱Free Monads for Less (Part 3 of 3): Yielding IO(在「誰需要真實世界?」或Idris' implementation of IO下) - 但請記住,IO Monad在Haskell中是不透明和抽象的;除非您正在編寫main(應用程序),否則不要指望能夠從IO a值中獲得a值。