在Haskell中,是否有一些标准函数将可能包含分钟和秒的字符串(即类似34m30s
之类)转换为适当的Maybe Double
分钟?因此,在这种情况下,我们会将34m30s
转换为Just 34.5
。
答案 0 :(得分:2)
您可以使用Data.Time.Format.parseTimeM
将String
转换为TimeOfDay
,然后将其转换为DiffTime
和Double
。
import Data.Time
parseMS :: String -> Maybe Double
parseMS = fmap (realToFrac . (/ 60) . timeOfDayToTime) . parseTimeM False defaultTimeLocale "%Mm%Ss"
答案 1 :(得分:2)
基于parseTimeM
的答案似乎只有在分钟和秒数恰好是两位数时才有效,因此parseMS "1m30s"
和parseMS "12m0s"
都会产生Nothing
。
你真的需要一个简单的解析器。这是在List monad中使用reads
调用的一个。请注意,它将需要带有“m”和“s”后缀的分钟和秒钟部分,因此“10m”和“10m30”和“15s”都将产生Nothing
。此外,它会接受负数和前导空格,因此" 10m -30s"
会返回Just 9.5
。
import Data.Maybe (listToMaybe)
readMS :: String -> Maybe Double
readMS str = listToMaybe $ do
(mins, 'm':rest1) <- reads str
(secs, "s") <- reads rest1
return (fromIntegral (mins :: Int) + fromIntegral (secs :: Int) / 60)
有些人在使用等效列表理解编写时更容易理解,如下所示:
readMS1 :: String -> Maybe Double
readMS1 str = listToMaybe
[ fromIntegral (mins :: Int) + fromIntegral (secs :: Int) / 60
| (mins, 'm':rest1) <- reads str
, (secs, "s") <- reads rest1
]
如果您之前没有看过这种风格,请注意:我们正在使用List monad,每个reads
调用都会返回一个可能的解析列表(value,rest_of_string)
对。 do-block的第一行获得整数mins
的每个可能的解析,后跟字母“m”加上字符串的rest1
。第二行将每个可能的rest1
解析为整数secs
,后跟字母“s”,而不是其他任何内容。
如果匹配失败(例如,字符串末尾没有“s”),则monad / comprehension返回空列表。否则,它返回所有可能解析的计算双打列表(在这种情况下,最多只有一个)。 listToMaybe
函数将空列表转换为Nothing
并抓取任何其他列表的头部以获得唯一答案。