List of showables: OOP beats Haskell?

后端 未结 8 1290
无人及你
无人及你 2020-12-24 06:46

I want to build a list of different things which have one property in common, namely, they could be turned into string. The object-oriented approach is straightforward: defi

8条回答
  •  猫巷女王i
    2020-12-24 07:20

    You can create your own operator to reduce syntax noise:

    infixr 5 <:
    
    (<:) :: Show a => a -> [String] -> [String]
    x <: l = show x : l
    

    So you can do:

    λ > (1 :: Int) <: True <: "abs" <: []
    ["1","True","\"abs\""]
    

    This is not [1 :: Int, True, "abs"] but not much longer.

    Unfortunately you cannot rebind [...] syntax with RebindableSyntax.


    Another approach is to use HList and preserve all type information, i.e. no downcasts, no upcasts:

    {-# LANGUAGE ConstraintKinds       #-}
    {-# LANGUAGE DataKinds             #-}
    {-# LANGUAGE GADTs                 #-}
    {-# LANGUAGE PolyKinds             #-}
    {-# LANGUAGE TypeFamilies          #-}
    {-# LANGUAGE TypeOperators         #-}
    {-# LANGUAGE UndecidableInstances  #-}
    
    import GHC.Exts (Constraint)
    
    infixr 5 :::
    
    type family All (c :: k -> Constraint) (xs :: [k]) :: Constraint where
      All c '[]       = ()
      All c (x ': xs) = (c x, All c xs)
    
    data HList as where
      HNil :: HList '[]
      (:::) :: a -> HList as -> HList (a ': as)
    
    instance All Show as => Show (HList as) where
      showsPrec d HNil       = showString "HNil"
      showsPrec d (x ::: xs) = showParen (d > 5) (showsPrec 5 x)
                             . showString " ::: "
                             . showParen (d > 5) (showsPrec 5 xs)
    

    And after all that:

    λ *Main > (1 :: Int) ::: True ::: "foo" ::: HNil
    1 ::: True ::: "foo" ::: HNil
    
    λ *Main > :t (1 :: Int) ::: True ::: "foo" ::: HNil
    (1 :: Int) ::: True ::: "foo" ::: HNil
      :: HList '[Int, Bool, [Char]]
    

    There are various ways to encode heterogenous list, in HList is one, there is also generics-sop with NP I xs. It depends on what you are trying to achieve in the larger context, if this is this preserve-all-the-types approach is what you need.

提交回复
热议问题