Haskell, create "multi-type" list - haskell

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.

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.

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.

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

Related

Checking constraints at runtime

I'm trying to define a function that detects whether the type of an input satisfies a given constraint:
satisfies :: (c a => a -> b) -> a -> Maybe b
-- or the more general
claim :: (c => a) -> Maybe a
So the desired behaviour would be:
>>> :t satisfies #Show show
satisfies #Show show :: a -> Maybe String
>>> satisfies #Show show (0 :: Int)
Just "0"
>>> satisfies #Show show (id :: Int -> Int)
Nothing
The goal is to make it easy to define fully polymorphic functions that take
advantage of specializations when possible:
showAny :: a -> String
showAny (satisfies #Show show -> Just str) = str
showAny (satisfies #Typeable showType -> Just str) = "_ :: " ++ str
showAny _ = "_"
As the easiest thing I could try, my first attempt tried using -fdefer-to-runtime
{-# OPTIONS_GHC -fdefer-type-errors -Wno-deferred-type-errors #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE RankNTypes #-}
module Claim where
import System.IO.Unsafe (unsafePerformIO)
import System.IO.Error (catchIOError)
satisfies :: (c a => a -> b) -> a -> Maybe b
satisfies f a = unsafePerformIO $
(return . Just $! f a) `catchIOError` \_ -> return Nothing
This failed because -fdefer-type-errors doesn't defer the checking to
runtime, or allow further checking to be done in the context which it is
actually used (as I had hoped), but instead at compile time replaces found
type errors with the equivalent of error "MESSAGE".
Now I'm out of ideas. Is implementing satisfies even possible?
You can't dispatch on instance availability at runtime. Remember, a constraint is translated by the compiler into a type class dictionary - a record of functions that is passed around explicitly and accessed explicitly at runtime. The "fat arrow" => is represented at runtime by a "thin arrow" ->, so the elaborator needs to know at compile time which dictionary to pass around.
That is, the following crude example:
class Show a where
show :: a -> String
instance Show String where
show = id
showTwice :: Show a => a -> String
showTwice x = show x ++ show x
main = putStrLn $ showTwice "foo"
generates Core code which looks approximately like:
data Show_ a = Show_ { show :: a -> String }
showString_ :: Show_ String
showString_ = Show_ { show = id }
showTwice :: Show_ a -> a -> String
showTwice show_ x = show show_ x ++ show show_ x
main = putStrLn $ showTwice showString_ "foo"
When generating code for main, the compiler needs to know where to find showString_.
You can imagine a system wherein you can look up a type class dictionary at runtime with some sort of introspection mechanism, but this would produce weird behaviour from a language design perspective. The problem is orphan instances. If I write a function which attempts to look up a given instance in module A, and define such an instance in an unrelated module B, then the behaviour of that function when called from some client module C depends on whether B was imported by some other part of the program. Pretty strange!
A more usual way of doing "fully polymorphic functions that take advantage of specializations when possible" would be to put the function in question into a type class itself and give it a default implementation (perhaps with a default signature if the default implementation depends on some superclass). Your showAny would then look like this:
{-# LANGUAGE DefaultSignatures #-}
import Data.Typeable
class ShowAny a where
showAny :: a -> String
default showAny :: Typeable a => a -> String
showAny x = "_ :: " ++ show (typeOf x)
You'd need to implement ShowAny for all of the types with which you want to use showAny, but that's usually a single line of code,
instance (Typeable a, Typeable b) => ShowAny (a -> b)
and you can specialise an implementation for a given type just by overriding showAny.
instance ShowAny String where
showAny = id
You see this approach quite frequently in libraries which do generic programming. aeson, for example, can use GHC.Generics to serialise a given type to and from JSON (all you have to do is derive Generic and write two lines instance ToJSON MyType; instance FromJSON MyType), but you can also write your own instances of ToJSON and FromJSON if the generic code isn't fast enough or you need to customise the output.
An alternate workaround to the accepted answer is to pass the dictionaries around manually.
That is, given:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
module Claim where
data Proof c where QED :: c => Proof c
type Claim c = Maybe (Proof c)
type c ? a = Maybe (Proof (c a))
One can write:
showAny :: (Show? a, Typeable? a) -> a -> String
showAny (Just QED, _) a = show a
showAny (_, Just QED) a = "_ :: " ++ showType a
showAny _ _ = "_"
Which works accepably well:
>>> showAny (Nothing, Just QED) (id :: Int -> Int)
"_ :: Int -> Int"
>>> showAny (Just QED, Just QED) (0 :: Int)
"0"
>>> showAny (Nothing, Nothing) undefined
"_"

Optimisation based on function result type

Below is a perhaps silly example, but I think solving this will solve another problem I have, detailed in this question.
I want to write a function with this signature:
myread :: (Read a) => String -> a
such that, myread = read, except when a ~ Int, in which case myread _ = 0.
Obviously this function is silly itself, but the point is I want to optimise based on return type.
Rewrite rules, or anything is fine here. For my actual problem, if the solution is a rewrite rule, it doesn't matter if there's cases where it doesn't fire, but I'd like the answer to at least give an example where it does.
You can do this directly with rewrite rules, in (perhaps) the obvious way, if you recall that the left hand side of a rule is in an expression context, not in a pattern context. In particular, type applications in the left hand side are perfectly valid.
{-# LANGUAGE TypeApplications #-}
module A where
{-# INLINE [1] myread #-}
{-# RULES "myread" forall s . myread #Int s = 0 #-}
myread :: Read a => String -> a
myread = read
Even without type applications, the following is also perfectly valid (but may not be in general, e.g. if the output type was f a and you wanted to 'optimize' only f, you could not have .. = (result :: [ _ ])):
{-# RULES "myread" forall s . myread s = (0 :: Int) #-}
And as an example use
module B where
import A
fun :: String -> String -> (Int, Bool)
fun x y = (myread x, myread y)
The proof that the rule fires is always to look at core, of course (irrelevant bits omitted):
fun4 :: Int
fun4 = I# 0#
fun :: String -> String -> (Int, Bool)
fun =
\ _ (w1 :: String) ->
(fun4,
case readEither6 (run fun3 w1) of _ {
[] -> fun2;
: x ds ->
case ds of _ {
[] -> x;
: ipv ipv1 -> fun1
}
})
Note, this is really a comment and not an answer simply because I'm not sure what exactly the goal is, but the code wouldn't fit a comment.
How about defining a new class with undecidable instances?
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
class MyRead a where
myread :: String -> a
instance {-# OVERLAPPABLE #-} Read a => MyRead a where
myread = read
instance MyRead Int where
myread = const 0
main = do
print $ (myread "True" :: Bool) -- True
print $ (myread "\"string\"" :: String) -- "string"
print $ (myread "12" :: Int) -- 0

Constrained Value Types in Haskell

Is it possible to define constrained types in Haskell, i.e. I would like to be able to express,
Prelude> let legalCharacters = ' ':['A'..'Z']
Prelude> legalCharacters
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
as a type, if possible.
Can be done in modern GHC (>= 7.10, perhaps already 7.8).
{-# LANGUAGE KindSignatures, DataKinds, MonoLocalBinds #-}
import GHC.TypeLits
newtype LegalChar (legalSet :: Symbol)
= LegalChar {getLegalChar :: Char}
deriving (Show)
fromChar :: KnownSymbol legal => Char -> Maybe (LegalChar legal)
fromChar c
| c`elem`symbolVal r = Just r
| otherwise = Nothing
where r = LegalChar c
Then
*Main> fromChar 'a' :: Maybe (LegalChar "abc")
Just (LegalChar {getLegalChar = 'a'})
*Main> fromChar 'x' :: Maybe (LegalChar "abc")
Nothing
I think in GHC-8 you can even give legalSet the kind String and do away with the KnownSymbol constraint, not sure how that would work.

How to convert arbitrary type to string, without adding extra quotes to strings?

I want to define a function which converts to strings, like the following 'toString':
toString 1 = "1"
toString True = "True"
toString "1" = "1"
Note that 'show' does not do this. By contrast it does the following:
show 1 = "1"
show True = "True"
show "1" = "\"1\""
That is, it adds extra quotes around strings. In this case I don't want to add extra quotes if I already have a string.
I'm considering using something like:
import Data.Typeable
toString a :: (Show a) => a -> String
toString a
| typeOf a == typeOf "" = a
| otherwise = show a
Are there any pitfalls in doing such a weird type-based conditional? Is there some built-in Haskell function that would be better to use instead?
This sort of ad-hoc polymorphism is permitted through type-classes. However, they will have to be overlapping since you want a catch all case:
{-# LANGUAGE FlexibleInstances, UndecideableInstances #-}
class Print a where
makeString :: a -> String
instance {-# OVERLAPPING #-} Print String where
makeString s = s
instance Show a => Print a where
makeString x = show x
Then, your function is makeString :: Print a => a -> String and it has an instance for everything that has a Show instance. To have the second instance, you need FlexibleInstances (the instance head is not of the usual form) and UndecideableInstances (since the constraint is as general as the instance head, GHC can't be sure that it won't fall into an infinite loop trying to solve these constraints).
If you want something like Alec's approach without overlapping instances, you can get it with a type family.
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, ScopedTypeVariables, UndecidableInstances, FlexibleInstances, DataKinds, ... whatever else GHC tells you it needs #-}
import Data.Text (Text, unpack)
import Data.Proxy
class Print a where
makeString :: a -> String
data Name = NString | NText | NShow
type family Choose a where
Choose [Char] = 'NString
Choose Text = 'NText
Choose _ = 'NShow
class Print' (n :: Name) a where
makeString' :: proxy n -> a -> String
instance (Choose a ~ n, Print' n a) => Print a where
makeString = makeString' (Proxy :: Proxy n)
instance a ~ String => Print' 'NString a where
makeString' _ = id
instance a ~ Text => Print' 'NText a where
makeString' _ = unpack
instance Show a => Print' 'NShow a where
makeString' _ = show
Expanding the OP solution attempt into a working one:
import Data.Typeable
toString :: (Show a, Typeable a) => a -> String
toString x = case cast x of
Just y -> y
Nothing -> show x

Constraints on closed type families?

I'd like to write a horribly non-parametric version of a function of type
pretty :: (Show a) => a -> Text
such that
pretty :: Text -> Text = id
pretty :: String -> Text = T.pack
pretty :: (Show a) => a -> Text = T.pack . show
So the idea is that anything that already has a Show instance can be turned into a "pretty" Text by just show-ing it, except for Text and String which we want to special-case.
The following code works:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, FlexibleContexts #-}
{-# LANGUAGE DataKinds, ConstraintKinds #-}
module Pretty (pretty) where
import Data.Text (Text)
import qualified Data.Text as T
type family StringLike a :: Bool where
StringLike String = True
StringLike Text = True
StringLike a = False
class (b ~ StringLike a) => Pretty' a b where
pretty' :: a -> Text
instance Pretty' String True where
pretty' = T.pack
instance Pretty' Text True where
pretty' = id
instance (Show a, StringLike a ~ False) => Pretty' a False where
pretty' = T.pack . show
type Pretty a = (Pretty' a (StringLike a))
pretty :: (Pretty a) => a -> Text
pretty = pretty'
and it can be used without exporting anything except the pretty function.
However, I am not too happy about the type signature for pretty:
pretty :: (Pretty a) => a -> Text
I feel that since StringLike is a closed type family, there should be a way for GHC to figure out that if only (Show a) holds, (Pretty a) is already satisfied, since:
The following hold trivially just by substituting the results of applying StringLike:
(StringLike String ~ True, Pretty' String True)
(StringLike Text ~ True, Pretty' Text True)
For everything else, we also know the result of applying StringLike:
(Show a, StringLike a ~ False) => (Pretty' a (StringLike a))
Is there a way to convince GHC of this?
I feel that since StringLike is a closed type family, there should be a way for GHC to figure out that if only (Show a) holds, (Pretty a) is already satisfied
To do that would require type inspection, and would break parameteric polymorphism. Consider defining a type family
type family IsInt a :: Bool where
IsInt Int = True
IsInt a = False
class (b ~ IsInt a) => TestInt a b where
isInt :: a -> Bool
instance TestInt Int True where
isInt _ = True
instance (IsInt a ~ False) => TestInt a False where
isInt _ = False
Now by your argument, GHC should be able to satisfy TestInt a from (). In other words, we should be able to test for any given type whether it is equal to Int. This is clearly impossible.
Similarly, a Show a dictionary is equivalent to a function a -> ShowS. How would you be able to decide, given just that, whether the argument is StringLike?
Maybe I misunderstood your goal but this seems like a lot of work to get the type you want.
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, UndecidableInstances, IncoherentInstances #-}
module Prettied where
import Data.Text (Text, pack)
class Pretty a where pretty :: a -> Text
instance Pretty Text where pretty = id
instance Pretty String where pretty = pack
instance Show a => Pretty a where pretty = pack . show
While it may seem that pretty should have type Pretty a => a -> Text, due to IncoherentInstances it will actually have type Show a => a -> Text. This should probably be in its own module because enabling IncoherentInstances is one of those things that can break valid code.

Resources