簡體   English   中英

haskell 中的 main 函數而不是 ghci

[英]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

假設您已經使用cabalstack創建了一個項目,那么您的Expr模塊應該在src/Expr.hs ,您的Main模塊應該在src/Main.hsapp/Main.hs 您擁有的代碼乍一看應該可以正常編譯和運行。

然后,您可以在項目目錄中運行 REPL 實例( cabal replstack repl )並從那里調用main函數,或者您可以將其作為可執行文件( cabal runstack runstack 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM