在Haskell中将引用列表转换为普通列表

时间:2014-05-29 23:44:33

标签: string list haskell

我知道如何使用readString更改为Int,例如使用

 map read ["3","2","1"] :: [[Int]]

但是当我遇到不规则的名单时,我就陷入困境,比如

["3","[3,5]","[5,3]"],["4","[1,9]","[2,3]"]

如何将其转换为[[3,[3,5],[5,3]],[4,[1,9],[2,3]]

2 个答案:

答案 0 :(得分:3)

在Haskell中无法实现您的目标,因为值[[3, [3, 5], [5, 4]], [4, [1, 9], [2, 3]]的类型无效。那里没有足够的近距离括号,你只有一个短。 [3, [3, 5]]的类型是什么? [[Int]][Int]?两者都不合适。

即使你的例子也错了:

> map read ["3", "2", "1"] :: [[Int]]
[*** Exception: Prelude.read: no parse

因为[3, 2, 1]的类型为[Int],而不是[[Int]]。请记住,这不是Python,列表只能包含单一类型的元素。


相反,如果你有像["3", "[3,5]", "[5,3]"]这样的输入,你可以用更像

的东西来解析它
import Text.Read (readMaybe)

readEither :: (Read a, Read b) => String -> Maybe (Either a b)
readEither s = case readMaybe s of
    Just x -> Just $ Left x
    Nothing -> case readMaybe s of
        Just y -> Just $ Right y
        Nothing -> Nothing

这可以表达得更短,但我认为这很好地说明了这一点。然后,您可以使用它来解析您的值:

parseMyList :: [String] -> [Maybe (Either Int [Int])]
parseMyList = map readEither

并将其用作

> parseMyList ["3", "[3,5]", "[5,3"]  -- Incomplete last element!
[Just (Left 3), Just (Right [3,5]), Nothing]

我在那里留下了一个意外的错字,所以你可以看到它也没有优雅地失败。


可以使用Monoid

编写更短的实现
import Text.Read (readMaybe)
import Data.Monoid

readEither :: (Read a, Read b) => String -> Maybe (Either a b)
readEither = getFirst $ mconcat $ map First [fmap Left $ readMaybe s, fmap Right $ readMaybe s]

也许有人可以打高尔夫球。

答案 1 :(得分:0)

使用readMaybe作为bheklilr,我认为你可能会使用[[Int]]作为结果数据类型。

> import Text.Read (readMaybe)
> map (\x->maybe [read x] id $ readMaybe x) ["3", "[3,5]", "[5,3]"] :: [[Int]]
[[3],[3,5],[5,3]]

如果你想要一个平面列表,你甚至可以在结果上使用concat