代码之家  ›  专栏  ›  技术社区  ›  developer_hatch

Haskell,创建“多类型”列表

  •  0
  • developer_hatch  · 技术社区  · 7 年前

    有没有办法让haskell输入这个表达式?

    ls  = [4, 3.2, True, "home"] 
    

    这是一个朋友给我的挑战,但没有想法,也没有告诉我这是否可能,所以也许我在浪费宝贵的时间。

    3 回复  |  直到 7 年前
        1
  •  2
  •   freestyle    7 年前

    作为笑话,你可以这样做:

    {-# LANGUAGE OverloadedStrings #-}
    
    import Data.String                                                          
    
    instance Num Bool where                                                     
        fromInteger 0 = False
        fromInteger _ = True
    
    instance Fractional Bool where
        fromRational 0 = False
        fromRational _ = True
    
    instance IsString Bool where
        fromString "" = False
        fromString _  = True
    
    ls = [4, 3.2, True, "home"]
    

    但这没有道理。


    如果表达的形式不是基本的,那么正如在评论中所写的那样,您可以使用 ExistentialType . 但有许多变体可以做到这一点。从使用 Data.Dynamic 自定义存在类型。

    例如 数据动态 :

    import Data.Dynamic
    
    ls = [toDyn (4 :: Int), toDyn (3.2 :: Double), toDyn True, toDyn "hello"]
    

    使用自定义类型:

     {-# LANGUAGE ExistentialQuantification #-}
    
     data Any = forall a. {- here can be restrictions on `a` => -} Any a
    
     ls :: [Any]
     ls = [Any (4 :: Int), Any (3.2 :: Double), Any True, Any "home"] 
    

    如果类型集已关闭,则可以仅使用ADT:

     data Variant = I Int | D Double | B Bool | S String
    
     ls :: [Variant]
     ls = [I 4, D 3.2, B true, S "home"]
    

    所以,要选择正确的解决方案,需要更多地了解您的问题。

        2
  •  1
  •   Adam Wagner    7 年前

    如果您只想打印列表中的所有内容,那么可以使用existicquantification来“隐藏”这样一个事实,即类型除了具有 Show 实例(或您关心的任何实例)。

    下面是一个简单的例子(请注意语言扩展——我知道这在GHC中有效,但不确定其他编译器):

    {-# LANGUAGE ExistentialQuantification #-}
    
    data Obj = forall a. (Show a) => Obj a
    
    ls :: [Obj]
    ls  = [Obj 4, Obj 3.2, Obj True, Obj "home"] 
    
    printObj :: Obj -> IO ()
    printObj (Obj x) = putStrLn (show x)
    
    main = mapM printObj ls
    

    请注意,您的列表与问题中的列表并不完全相同,但是 Obj 可以采用具有 显示 例子

        3
  •  0
  •   developer_hatch    7 年前

    我发现了一些有趣的东西,可能已经足够近了, here

    data Showable a = forall a. Show a => MkShowable a
    
    pack :: Show a => a -> Showable
    pack = MkShowable
    
    hlist :: [Showable]
    hlist = [ pack 3
            , pack "house"
            , pack True
            , pack 'y'
            , pack (Just Nothing) ]
    
    res = map (\(MkShowable v) -> show v) hlist