在Haskell中从未知序列创建不同类型?

假设一个函数“获取”一个信息序列(例如一个字符列表),并且应该从中创建不同的类型,其中它的类型取决于输入序列,它表示内容 - 并假设类型已经给出。

numFromString :: [Char] -> ???

我想有几种可能性。

我的第一个想法是使用类型参数。

main :: IO ()
main =
    do
        sLine <- getLine
        print $ numFromString sLine

numFromString :: (Show a, Read a) => String -> (Maybe a)
numFromString ('I':'n':'t':'e':'g':'e':'r':rs) = Just ((read rs) :: Integer)
--                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this does not work
numFromString ('I':'n':'t':rs) = Just ((read rs) :: Int)
numFromString _ = Nothing

...但我们不能只提供一个 Integer 类型变量,或者我们可以吗?。

我的第二个想法是使用类型类

main :: IO ()
main = 
    do
        sLine <- getLine
        print $ ((numFromString sLine) :: (Maybe Integer))
        --                                ^^^^^^^^^^^^^^^ I have to decide in advance which type I want to get

class (Show a, Read a) => XClass a where
    numFromString :: String -> (Maybe a)

instance XClass Int where
    numFromString ('I':'n':'t':rs) = Just ((read rs) :: Int)
    numFromString _ = Nothing

instance XClass Integer where
    numFromString ('I':'n':'t':'e':'g':'e':'r':rs) = Just ((read rs) :: Integer)
    numFromString _ = Nothing

...但这也不起作用,当我们使用 numFromString 时,是吗?

我的第三个想法是使用 sum 类型的数据类型。

main :: IO ()
main =
    do
        sLine <- getLine
        print $ numFromString sLine

data X = XInt Int | XInteger Integer | XNone
    deriving Show

numFromString :: String -> X
numFromString ('I':'n':'t':'e':'g':'e':'r':rs) = XInteger (read rs)
numFromString ('I':'n':'t':rs) = XInt (read rs)
numFromString _ = XNone

有没有更优雅的方式?

泛型编程有帮助吗?

它会是什么样子?

回答

您的总和类型方法对我来说是正确的方法。

例如:

  • JSON 文档的第一个字符决定了类型——{对于对象、[对于列表、"字符串等aeson,流行的 Haskell JSON 解析器使用可以表示其中每一个的 sum 类型。
  • 解析 CBOR 涉及几乎相同的情况。cborg使用sum 类型来捕获所有可能性。
  • 智能游戏格式可以代表各种游戏的走法记录。存储移动所需的信息类型因游戏而异。该sgf库使用sum 类型来捕捉可能性。

...等等。


以上是在Haskell中从未知序列创建不同类型?的全部内容。
THE END
分享
二维码
< <上一篇
)">
下一篇>>