Tôi đang sử dụng thực hiện này của maybeRead
:Haskell: đọc một số (Integer hoặc Floating point)
maybeRead :: (Read a) => String -> Maybe a
maybeRead = fmap fst . listToMaybe . filter (null . dropWhile isSpace . snd) . reads
và riêng getNum
chức năng của tôi mà nhắc đến khi nó được đầu vào hợp lệ:
getNum :: (Num a, Read a) => String -> IO a
getNum s = do
putStr s
input <- fmap maybeRead getLine
if isNothing input
then getNum s
else return $ fromJust input
Tuy nhiên nếu tôi nhập 5.2
thì nó coi đó là đầu vào kém — Tại sao? Có số lần xuất hiện là Int
và Integer
trong mã của tôi. Tôi chỉ đang sử dụng Num
, vì tôi muốn chấp nhận bất kỳ loại số nào.
Nếu tôi gọi nó rõ ràng là getNum "Enter a number: " :: IO Double
thì nó hoạt động. Tôi có phải làm việc này không? Là hệ thống kiểu Haskell chỉ lừa tôi nghĩ tôi có thể làm điều này khi thực sự nó là không thể mà không gõ đầy đủ năng động? Nếu vậy thì tại sao mã của tôi thậm chí biên dịch; tại sao nó giả định số nguyên?
Ghi chú phong cách nhỏ: Tốt hơn là sử dụng mẫu khớp với 'isNothing' và' fromJust', vì vậy biểu thức 'if' có thể được thay thế bằng' trường hợp đầu vào Không có gì -> getNum s; Chỉ cần x -> return x'. – hammar
Cảm ơn, điều đó có vẻ tốt hơn rất nhiều. – mk12