haskell - 阅读 int 孤立地工作,但如何让它在这个脚本中工作?
问题描述
当我尝试调用 read 来读取Int32
时,它在 GHCi 中工作:
$ ghci
GHCi, version 8.4.4: http://www.haskell.org/ghc/ :? for help
Prelude> import Data.Int
Prelude Data.Int> let fooInt32 :: Int32; fooInt32 = read "6531"
Prelude Data.Int> :t fooInt32
fooInt32 :: Int32
Prelude Data.Int> fooInt32
6531
但是,在我的应用程序中,我收到此错误(使用包装读取以获得更好的错误消息):
readInt32.hs: read error, reading: '6531'
CallStack (from HasCallStack):
error, called at /home/brandon/workspace/ProjectGists/Haskell/ReadInt32/readInt32.hs:27:9 in main:Main
这是一个独立的堆栈脚本,它举例说明了错误:
#!/usr/bin/env stack
-- stack --resolver lts-13.14 script
{-# LANGUAGE OverloadedStrings #-}
import Data.Int
import Data.Maybe (fromJust, isJust, listToMaybe)
import Data.String (IsString(..))
import Data.Text (Text, pack, splitOn, unpack)
import Data.Time.Calendar (Day(..))
import Data.Time.Clock (UTCTime(..))
import Data.Typeable
newtype CowMark = CowMark {unCowMark :: Int32}
deriving (Eq, Ord, Read, Show, Typeable)
newtype TableName = TableName {unTableName :: Text}
deriving (Eq, Ord, Read, Show)
instance IsString TableName where
fromString str = TableName $ pack str
type CowRecordKey = (TableName, CowMark, UTCTime)
read' :: Read a => String -> a
read' s = case reads s of
[(x,"")] -> x
_ -> error $ " read error, reading: '" ++ s ++ "'"
rep2Key :: String -> Maybe CowRecordKey
rep2Key strKey = do
splList <- return $ splitOn "_" (pack strKey)
(tblName, mrkStr, timeStr) <- head3 splList
miInt <- read' (unpack mrkStr)
timeOut <- read (unpack timeStr)
return $ (TableName $ tblName, CowMark miInt, timeOut)
where
head3 :: [a] -> Maybe (a, a, a)
head3 list@(_:x2:xs) = do
mx1 <- listToMaybe list
mx2 <- listToMaybe (x2:xs)
mx3 <- listToMaybe xs
return (mx1, mx2, mx3)
head3 _ = Nothing
cowRecKey1 :: CowRecordKey
cowRecKey1 = (
TableName "SxRecord"
, CowMark 6531
, UTCTime (ModifiedJulianDay 3234) 0
)
cowRecKeyStr1 :: String
cowRecKeyStr1 = "SxRecord_6531_1867-09-25 00:00:00"
main = do
key1 <- return $ rep2Key cowRecKeyStr1
print key1
不知道该怎么做。我也尝试过注释miInt :: Int32
以查看是否有帮助,但没有。
解决方案
我已read'
在您的脚本中使用预期的类型进行了注释:
read' :: String -> Int32
read' s = case reads s of
[(x,"")] -> x
_ -> error $ " read error, reading: '" ++ s ++ "'"
并立即得到一个错误:
• Couldn't match expected type ‘Maybe Int32’
with actual type ‘Int32’
• In a stmt of a 'do' block: miInt <- read' (unpack mrkStr)
实际上,do
块 inrep2Key
是在Maybe
上下文中运行的,所以该行
miInt <- read' (unpack mrkStr)
绑定miInt :: Int32
,但右边的表达式具有类型Maybe Int32
。这就是为什么注释miInt
本身并没有指出问题所在。
如果您想使解析失败 (?),请更改read'
为返回 a Maybe
,如下所示:
read' :: Read a => String -> Maybe a
read' s = case reads s of
[(x,"")] -> Just x
_ -> Nothing
如果要保留error
行为(和read'
签名),或者对于返回纯值的任何其他函数,可以将行更改rep2Key
为
let miInt = read' (unpack mrkStr)
HeremiInt
绑定到右侧的值而不调用>>=
,因此它应该是相同的类型(Int32
没有Maybe
)。
Hoogle搜索显示,最后一个函数作为Text.Read.readMaybe存在于 Prelude 中。
推荐阅读
- node.js - Firebase 函数和 twilio
- python - 从simpy中的线性组合生成列表
- cluster-computing - 点燃。活跃(真)?
- python - 如何根据数据框A和B的列之间的多个条件向数据框A添加一列?
- c# - 我可以根据文件夹使用不同的 web.config 文件吗?
- java - 使用 Java 中的 Jackson 在多行上编写 JSON 数组
- python - 使用索引之间的 1d 查找对 3d numpy 数组进行切片
- mongodb - 将一个集合的所有列数据复制到mongodb中的另一个集合中
- node.js - 如何验证 Node API 的请求者
- ios - 为什么 GeoFire 查询有时会使用以前加载的数据?