0

Is there a way to make haskell type this expression?

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

It's a challenge a friend gived to me, but no ideas come around, also didn't tell me if that is possible, so maybe I'm wasting precious time.

8
  • 1
    The types it contains are completely arbitrary? Commented Nov 2, 2017 at 13:46
  • 1
    Not exactly that expression, but you can use arbitrary types in a list with wiki.haskell.org/Existential_type, but working with these values after they are in the list is very limited, because types of these are checked at compile-time, rather than run time - this is generally considered an antipattern. Commented Nov 2, 2017 at 13:50
  • 1
    What use would such list be? What are you going to do with it afterwards? The answer to this question will determine how to do it. Commented Nov 2, 2017 at 13:51
  • @FyodorSoikin supose I want to print all the element of that list Commented Nov 2, 2017 at 13:54
  • @DamianLattenero, then Existential Types can help you with that... look at section 2.1 here: wiki.haskell.org/Existential_type - the only caveat is that all of these types must have a Show instance, which makes sense, since I'm assuming you want to use print which requires a Show instance. Commented Nov 2, 2017 at 13:56

3 Answers 3

2

As joke, you can do like this:

{-# 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"]

But this doesn't have sense.


If the form of the expression is not fundamental, then as wrote in the comments, you can use the ExistentialType. But there are many variants to do that. From use Data.Dynamic to custom existential type.

For example, with Data.Dynamic:

import Data.Dynamic

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

With custom type:

 {-# 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"] 

If type set are closed, you can just use ADT:

 data Variant = I Int | D Double | B Bool | S String

 ls :: [Variant]
 ls = [I 4, D 3.2, B true, S "home"]

So, to select right solution need to know more about your issue.

Sign up to request clarification or add additional context in comments.

Comments

1

If you just want to print everything in the list, you can use ExistentialQuantification to "hide" the fact that the types are anything beyond having a Show instance (or whatever instance you care about).

Here's a simple example (note the language extension - I know this works in GHC, not sure about other compilers):

{-# 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

Notice that your list isn't strictly the same as in your question, but Obj can take any type that has a Show instance.

1 Comment

Hey I was thinking exactly the same! I think that's could be the most correct one, for now, I will accept that
0

I found something interesting that maybe is close enough, 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.