[英]main function in haskell instead of ghci
嗨,我是使用 haskell 的新手。
我實際上是在使用 ghci 來編譯這段代碼:
module Expr where
import Control.Applicative
import System.Environment
data Expr = Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Lit Integer
eval :: Expr -> Integer
eval e = case e of
Add a b -> eval a + eval b
Sub a b -> eval a - eval b
Mul a b -> eval a * eval b
Lit n -> n
-- Nouveau datatype nécessaire pour les instances
data Parser r = Parser {parse :: String -> Maybe (r, String)}
-- Instances
instance Functor Parser where
fmap f (Parser p) = Parser $ \s -> case p s of
Just (a, s') -> Just (f a, s')
Nothing -> Nothing
instance Applicative Parser where
pure x = Parser $ \s -> Just (x, s)
Parser p1 <*> pp2 = Parser $ \s -> case p1 s of
Just (f, s') -> case parse pp2 s' of
Just (a, s'') -> Just (f a, s'')
Nothing -> Nothing
Nothing -> Nothing
instance Alternative Parser where
empty = Parser $ const Nothing
(Parser p1) <|> pp2 = Parser $ \s -> p1 s <|> parse pp2 s
-- Le reste est identique
runParser :: Parser a -> String -> Maybe a
runParser (Parser p) s = case p s of
Just (r, "") -> Just r
_ -> Nothing
check :: (Char -> Bool) -> Parser Char
check f = Parser $ \s -> case s of
(x:xs) | f x -> Just (x, xs)
_ -> Nothing
char :: Char -> Parser Char
char c = check (== c)
oneOf :: [Char] -> Parser Char
oneOf cs = check (\c -> elem c cs)
number :: Parser Integer
number = read <$> some digit
where digit = oneOf "0123456789"
expr :: Parser Expr
expr = add_sub
where
add_sub = binOp Add '+' mul <|> binOp Sub '-' mul <|> mul
mul = binOp Mul '*' factor <|> factor
factor = parens <|> lit
lit = Lit <$> number
parens = char '(' *> expr <* char ')'
binOp c o p = c <$> p <*> (char o *> p)
evalExpr :: String -> Maybe Integer
evalExpr s = (fmap eval) $ runParser expr $ concat $ words s
我想要做的是創建一個 Main 來自己編譯和運行此代碼,我正在努力這樣做。
到目前為止,我設法理解並且我希望有這樣的結構:
module Main where
import System.Environment
import Expr
main :: IO ()
main = do
args <- getArgs
case args of
[] -> putStrLn "No argument"
[s]-> evalExpr args
我想知道我是否可以使用 ghci 生成一個 main 或者是否有另一種解決方案來創建一個
您已經知道需要創建一個名為main
的常量,其類型為IO ()
。
讓我們從編譯錯誤開始。 出現這些是因為您縮進了main
操作的內容而不是do
關鍵字。 因為 Haskell 對空格敏感,這會使編譯器感到困惑。 所以你上面的例子實際上應該是這樣的:
main :: IO ()
main = do args <- getArgs
case args of [] -> putStrLn "No argument"
[s] -> evalExpr args
我無法告訴您這是否真的是您在main
操作中想要的,因為我不知道您想要它做什么,但它可能看起來與您在 GHCi 中運行的相似。
例如,如果您的 GHCi 會話如下所示:
Prelude> let x = foo bar
Prelude> print x
等效的main
如下所示:
main :: IO ()
main = do let x = foo bar
print x
假設您已經使用cabal
或stack
創建了一個項目,那么您的Expr
模塊應該在src/Expr.hs
,您的Main
模塊應該在src/Main.hs
或app/Main.hs
。 您擁有的代碼乍一看應該可以正常編譯和運行。
然后,您可以在項目目錄中運行 REPL 實例( cabal repl
或stack repl
)並從那里調用main
函數,或者您可以將其作為可執行文件( cabal run
或stack run
) stack run
並從命令傳遞參數-線。
如果您還沒有使用我上面提到的任何一種工具創建一個項目,那么這個文檔應該很有用:
編輯:
在/嘗試編譯和運行它之前,我忽略了詳細查看代碼。
您的主函數的模式匹配行存在一些問題:
[s] -> evalExpr args
由於您的evalExpr
函數采用String
您需要向它傳遞一些東西而不是args
,后者是[String]
類型。
此外, evalExpr
的結果是類型Maybe Integer
並且需要是IO ()
類型才能正確結束 case 語句。
如果你用這個替換它:
_ -> putStrLn . show $ evalExpr (unwords args)
然后stack run 1 + 1
運行stack run 1 + 1
將輸出Just 2
。
要使其作為獨立的可執行文件運行,您必須運行stack install
,這將在您的系統上創建一個您可以運行的可執行文件。 在我的輸出到~/.local/bin/Expr-exe
然后我可以調用它:
paul@Pauls-MacBook-Pro Expr % ~/.local/bin/Expr-exe 1 + 1
Just 2
(旁注: stack install
顯然是stack build --copy-bins
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.