簡體   English   中英

haskell-problem:io string - > [int]

[英]haskell-problem: io string -> [int]

你好偉大的程序員在那里,

我正在使用haskell的第一步,並且有一個令我困惑的功能:

import Data.List.Split
getncheck_guesslist = do
    line <- getLine
    let tmp = splitOneOf ",;" line
    map read tmp::[Int]

splitOneOf在Data.List.Split中(我用cabal安裝拆分安裝) splitOneOf :: (Eq a)=> [a]->[a]->[[a]]

從錯誤我得到它有一些類型不正確 - 但不知道如何解決這個沖突,因為IO對我來說仍然是一個謎

我想讀取用逗號或分號分隔的整數輸入,並得到一個整數列表,這樣:

  • 如何檢查用戶輸入是否為Int類型
  • 如何將“IO String”類型的輸入“轉換”為[Int]

提前感謝您的想法和提示 - 您的ε/ 2

當您編寫使用IO monad的函數時,要從函數返回的任何值也必須位於IO monad中。

這意味着,您不必返回類型為[Int]的值,而是返回類型為IO [Int] 要做到這一點,你可以使用return函數,它將值“包裝”到IO (它實際上適用於任何 monad)。

只需更改最后一行以使用return包裝您的值,如下所示:

getncheck_guesslist = do
    line <- getLine
    let tmp = splitOneOf ",;" line
    return (map read tmp :: [Int])

在Haskell中執行此操作的“正確方法”是將IO與其他所有內容分開。 您的代碼的直接翻譯將是這樣的:

getncheck_guesslist :: IO [Int]
getncheck_guesslist = do line <- getLine               -- get
                         return (check_guesslist line) -- check

check_guesslist :: String -> [Int]
check_guesslist line = let tmp = splitOneOf ",;" line
                       in map read tmp

請注意, getncheck_guesslist只是一個IO操作。 該函數沒有輸入參數 ,即使它確實需要來自getLine (IO)輸入

另請注意, getncheck_guesslist是對getLine IO操作的簡單修改。 是不是有一個組合器可以讓我推動一個函數來對monad中的值進行操作? 停止。 霍格時間!

我有一個功能(a -> b) 我有一個輸入類型的值,但它被卡在monad ma 我想執行的單子里面的功能,所以其結果將不可避免地被卡在單子太mb 把它們放在一起,我們hoogle (a -> b) -> ma -> mb 瞧, fmap正是我們想要的。

get_guesslist = check_guesslist `fmap` getLine
-- or, taking it a step further
get_guesslist = (map read . splitOneOf ",;") `fmap` getLine :: IO [Int]

最后要注意的,只要你喜歡的名字代碼的方法somethingAndSomethingElse ,通常最好的編碼風格來寫和調用somethingsomethingElse作為兩個獨立的方法。 對於最終版本,我只是將其重命名為get_guesslist ,因為從概念上講它就是它的作用。 它得到了作為Ints列表的猜測。

作為最后的最后一點,我已經離開了baroap開始的地步。 ;) fmap<$>相同。

如果IO monad中存在某些內容,則無法將其帶到純外部世界進行進一步處理。 相反,您傳遞純函數以在IO內的函數內部工作。

最后,您的程序讀取一些輸入並寫入一些輸出,因此您的主要功能將用於IO ,否則您將無法輸出任何內容。 而不是讀IO String和創建[Int]通過消耗該函數[Int]到您的主要功能和使用它里面do

import Data.List.Split
import Control.Applicative

getncheck_guesslist :: IO [Int]
getncheck_guesslist = map read . splitOneOf ",;" <$> getLine

每次代碼陷入foo >>= return . bar foo >>= return . bar ,該你做的,你不使用你的單子的單子功能脫糖的DO-塊(和糾正錯誤類型),但只有它的仿函數部分,即,不客氣的說,你是不是用搞亂IO部分的類型,但與aIO a

(<$>) :: (Functor f) => (a -> b) -> f a -> f b

fmap將是<$>的非中綴名稱。兩者都與map密切相關。)

上面的代碼對於ad-hoc代碼來說非常慣用,但是干凈的代碼看起來就像

import Data.Maybe

maybeRead :: Read a => String -> Maybe a
maybeRead = fmap fst . listToMaybe . reads 
                               -- That fmap is using "instance Functor Maybe"

parseGuessList :: String -> [Int]
parseGuessList =  catMaybes . map maybeRead . splitOneOf ",;"

getncheck_guesslist = parseGuessList <$> getLine

,或者,如果您不想忽略非int輸入但是錯誤輸出,

parseGuessList xs = if success then Just . catMaybes $ ys else Nothing 
  where ys :: String -> [Mabye Int]
        ys = map maybeRead . splitOneOf ",;" $ xs
        success = all isJust ys

(請注意,我只證明代碼是正確的,但實際上沒有嘗試過。)

如果它比你想要使用正確的解析庫更復雜,我想。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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