List of showables OOP-style in Haskell? - haskell

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: define interface Showable and make classes of interest implement it. Second point can in principle be a problem when you can't alter the classes, but let's pretend this is not the case. Then you create a list of Showables and fill it with objects of these classes without any additional noise (e.g. upcasting is usually done implicitly). Proof of concept in Java is given here.
My question is what options for this do I have in Haskell? Below I discuss approaches that I've tried and which don't really satisfy me.
Approach 1: existensials. Works but ugly.
{-# LANGUAGE ExistentialQuantification #-}
data Showable = forall a. Show a => Sh a
aList :: [Showable]
aList = [Sh (1 :: Int), Sh "abc"]
The main drawback for me here is the necessity for Sh when filling the list. This closely resembles upcast operations which are implicitly done in OO-languages.
More generally, the dummy wrapper Showable for the thing which is already in the language — Show type class — adds extra noise in my code. No good.
Approach 2: impredicatives. Desired but does not work.
The most straightforward type for such a list for me and what I really desire would be:
{-# LANGUAGE ImpredicativeTypes #-}
aList :: [forall a. Show a => a]
aList = [(1 :: Int), "abc"]
Besides that (as I heard)ImpredicativeTypes is “fragile at best and broken at worst”
it does not compile:
Couldn't match expected type ‘a’ with actual type ‘Int’
‘a’ is a rigid type variable bound by
a type expected by the context: Show a => a
and the same error for "abc". (Note type signature for 1: without it I receive even more weird message: Could not deduce (Num a) arising from the literal ‘1’).
Approach 3: Rank-N types together with some sort of functional lists (difference lists?).
Instead of problematic ImpredicativeTypes one would probably prefer more stable and wide-accepted RankNTypes. This basically means: move
desired forall a. Show a => a out of type constructor (i.e. []) to plain function types. Consequently we need some representation of lists as plain functions. As I barely heard there are such representations. The one I heard of is difference lists. But in Dlist package the main type is good old data so we return to impredicatives. I didn't investigate this line any further as I suspect that it could yield more verbose code than in approach 1. But if you think it won't, please give me an example.
Bottom line: how would you attack such a task in Haskell? Could you give more succinct solution than in OO-language (especially in place of filling a list — see comment for code in approach 1)? Can you comment on how relevant are the approaches listed above?
UPD (based on first comments): the question is of course simplified for the purpose of readability. The real problem is more about how to store things which share the same type class, i.e. can be processed later on in a number of ways (Show has only one method, but other classes can have more than one). This factors out solutions which suggest apply show method right when filling a list.

Since evaluation is lazy in Haskell, how about just creating a list of the actual strings?
showables = [ show 1, show "blah", show 3.14 ]

The HList-style solutions would work, but it is possible to reduce the complexity if you only need to work with lists of constrained existentials and you don't need the other HList machinery.
Here's how I handle this in my existentialist package:
{-# LANGUAGE ConstraintKinds, ExistentialQuantification, RankNTypes #-}
data ConstrList c = forall a. c a => a :> ConstrList c
| Nil
infixr :>
constrMap :: (forall a. c a => a -> b) -> ConstrList c -> [b]
constrMap f (x :> xs) = f x : constrMap f xs
constrMap f Nil = []
This can then be used like this:
example :: [String]
example
= constrMap show
(( 'a'
:> True
:> ()
:> Nil) :: ConstrList Show)
It could be useful if you have a large list or possibly if you have to do lots of manipulations to a list of constrained existentials.
Using this approach, you also don't need to encode the length of the list in the type (or the original types of the elements). This could be a good thing or a bad thing depending on the situation. If you want to preserve the all of original type information, an HList is probably the way to go.
Also, if (as is the case of Show) there is only one class method, the approach I would recommend would be applying that method to each item in the list directly as in ErikR's answer or the first technique in phadej's answer.
It sounds like the actual problem is more complex than just a list of Show-able values, so it is hard to give a definite recommendation of which of these specifically is the most appropriate without more concrete information.
One of these methods would probably work out well though (unless the architecture of the code itself could be simplified so that it doesn't run into the problem in the first place).
Generalizing to existentials contained in higher-kinded types
This can be generalized to higher kinds like this:
data AnyList c f = forall a. c a => f a :| (AnyList c f)
| Nil
infixr :|
anyMap :: (forall a. c a => f a -> b) -> AnyList c f -> [b]
anyMap g (x :| xs) = g x : anyMap g xs
anyMap g Nil = []
Using this, we can (for example) create a list of functions that have Show-able result types.
example2 :: Int -> [String]
example2 x = anyMap (\m -> show (m x))
(( f
:| g
:| h
:| Nil) :: AnyList Show ((->) Int))
where
f :: Int -> String
f = show
g :: Int -> Bool
g = (< 3)
h :: Int -> ()
h _ = ()
We can see that this is a true generalization by defining:
type ConstrList c = AnyList c Identity
(>:) :: forall c a. c a => a -> AnyList c Identity -> AnyList c Identity
x >: xs = Identity x :| xs
infixr >:
constrMap :: (forall a. c a => a -> b) -> AnyList c Identity -> [b]
constrMap f (Identity x :| xs) = f x : constrMap f xs
constrMap f Nil = []
This allows the original example from the first part of this to work using this new, more general, formulation with no changes to the existing example code except changing :> to >: (even this small change might be able to be avoided with pattern synonyms. I'm not totally sure though since I haven't tried and sometimes pattern synonyms interact with existential quantification in ways that I don't fully understand).

If you really, really want, you can use a heterogeneous list. This approach really isn't useful for Show, because it has a single method and all you can do is apply it, but if your class has multiple methods this could be useful.
{-# LANGUAGE PolyKinds, KindSignatures, GADTs, TypeFamilies
, TypeOperators, DataKinds, ConstraintKinds, RankNTypes, PatternSynonyms #-}
import Data.List (intercalate)
import GHC.Prim (Constraint)
infixr 5 :&
data HList xs where
None :: HList '[]
(:&) :: a -> HList bs -> HList (a ': bs)
-- | Constraint All c xs holds if c holds for all x in xs
type family All (c :: k -> Constraint) xs :: Constraint where
All c '[] = ()
All c (x ': xs) = (c x, All c xs)
-- | The list whose element types are unknown, but known to satisfy
-- a class predicate.
data CList c where CL :: All c xs => HList xs -> CList c
cons :: c a => a -> CList c -> CList c
cons a (CL xs) = CL (a :& xs)
empty :: CList c
empty = CL None
uncons :: (forall a . c a => a -> CList c -> r) -> r -> CList c -> r
uncons _ n (CL None) = n
uncons c n (CL (x :& xs)) = c x (CL xs)
foldrC :: (forall a . c a => a -> r -> r) -> r -> CList c -> r
foldrC f z = go where go = uncons (\x -> f x . go) z
showAll :: CList Show -> String
showAll l = "[" ++ intercalate "," (foldrC (\x xs -> show x : xs) [] l) ++ "]"
test = putStrLn $ showAll $ CL $
1 :&
'a' :&
"foo" :&
[2.3, 2.5 .. 3] :&
None

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.

I would do something like this:
newtype Strings = Strings { getStrings :: [String] }
newtype DiffList a = DiffList { getDiffList :: [a] -> [a] }
instance Monoid (DiffList a) where
mempty = DiffList id
DiffList f `mappend` DiffList g = DiffList (f . g)
class ShowList a where
showList' :: DiffList String -> a
instance ShowList Strings where
showList' (DiffList xs) = Strings (xs [])
instance (Show a, ShowList b) => ShowList (a -> b) where
showList' xs x = showList' $ xs `mappend` DiffList (show x :)
showList = showList' mempty
Now, you can create a ShowList as follows:
myShowList = showList 1 "blah" 3.14
You can get back a list of strings using getStrings as follows:
myStrings = getStrings myShowList
Here's what's happening:
A value of the type ShowList a => a could be:
Either a list of strings wrapped in a Strings newtype wrapper.
Or a function from an instance of Show to an instance of ShowList.
This means that the function showList is a variadic argument function which takes an arbitrary number of printable values and eventually returns a list of strings wrapped in a Strings newtype wrapper.
You can eventually call getStrings on a value of the type ShowList a => a to get the final result. In addition, you don't need to do any explicit type coercion yourself.
Advantages:
You can add new elements to your list whenever you want.
The syntax is succinct. You don't have to manually add show in front of every element.
It doesn't make use of any language extensions. Hence, it works in Haskell 98 too.
You get the best of both worlds, type safety and a great syntax.
Using difference lists, you can construct the result in linear time.
For more information on functions with variadic arguments, read the answer to the following question:
How does Haskell printf work?

My answer is fundamentally the same as ErikR's: the type that best embodies your requirements is [String]. But I'll go a bit more into the logic that I believe justifies this answer. The key is in this quote from the question:
[...] things which have one property in common, namely, they could be turned into string.
Let's call this type Stringable. But now the key observation is this:
Stringable is isomorphic to String!
That is, if your statement above is the whole specification of the Stringable type, then there is a pair functions with these signatures:
toString :: Stringable -> String
toStringable :: String -> Stringable
...such that the two functions are inverses. When two types are isomorphic, any program that uses either of the types can be rewritten in terms of the other without any change to its semantics. So Stringable doesn't let you do anything that String doesn't let you do already!
In more concrete terms, the point is that this refactoring is guaranteed to work no matter what:
At every point in your program where you turn an object into a Stringable and stick that into a [Stringable], turn the object into a String and stick that into a [String].
At every point in your program that you consume a Stringable by applying toString to it, you can now eliminate the call to toString.
Note that this argument generalizes to types more complex than Stringable, with many "methods". So for example, the type of "things that you can turn into either a String or an Int" is isomorphic to (String, Int). The type of "things that you can either turn into a String or combine them with a Foo to produce a Bar" is isomorphic to (String, Foo -> Bar). And so on. Basically, this logic leads to the "record of methods" encoding that other answers have brought up.
I think the lesson to draw from this is the following: you need a specification richer than just "can be turned into a string" in order to justify using any of the mechanisms you brought up. So for example, if we add the requirement that Stringable values can be downcast to the original type, an existential type now perhaps becomes justifiable:
{-# LANGUAGE GADTs #-}
import Data.Typeable
data Showable = Showable
Showable :: (Show a, Typeable a) => a -> Stringable
downcast :: Typeable a => Showable -> Maybe a
downcast (Showable a) = cast a
This Showable type is not isomorphic to String, because the Typeable constraint allows us to implement the downcast function that allows us to distinguish between different Showables that produce the same string. A richer version of this idea can be seen in this "shape example" Gist.

You can store partially applied functions in the list.
Suppose we are building a ray-tracer with different shape that you can intersect.
data Sphere = ...
data Triangle = ...
data Ray = ...
data IntersectionResult = ...
class Intersect t where
intersect :: t -> Ray -> Maybe IntersectionResult
instance Intersect Sphere where ...
instance Intersect Triangle where ...
Now, we can partially apply the intersect to get a list of Ray -> Maybe IntersectionResult such as:
myList :: [(Ray -> Maybe IntersectionResult)]
myList = [intersect sphere, intersect triangle, ...]
Now, if you want to get all the intersections, you can write:
map ($ ray) myList -- or map (\f -> f ray) myList
This can be extended a bit to handle an interface with multiples functions, for example, if you want to be able to get something of a shape :
class ShapeWithSomething t where
getSomething :: t -> OtherParam -> Float
data ShapeIntersectAndSomething = ShapeIntersectAndSomething {
intersect :: Ray -> Maybe IntersectionResult,
getSomething :: OtherParam -> Float}
Something I don't know is the overhead of this approach. We need to store the pointer to the function and the pointer to the shape and this for each function of the interface, which is a lot compared to the shared vtable usually used in OO language. I don't have any idea if GHC is able to optimize this.

The core of the problem is : you want to dispatch (read select which function to call) at runtime, depending on what the "type" of the object is. In Haskell this can be achieved by wrapping the data into a sum data type (which is called here ShowableInterface):
data ShowableInterface = ShowInt Int | ShowApple Apple | ShowBusiness Business
instance Show ShowableInterface where
show (ShowInt i) = show i
show (ShowApple a) = show a
show (ShowBusiness b) = show b
list=[ShowInt 2, ShowApple CrunchyGold, ShowBusiness MoulinRouge]
show list
would correspond to something like this in Java :
class Int implements ShowableInterface
{
public show {return Integer.asString(i)};
}
class Apple implements ShowableInterface
{
public show {return this.name};
}
class ShowBusiness implements ShowableInterface
{
public show {return this.fancyName};
}
List list = new ArrayList (new Apple("CrunchyGold"),
new ShowBusiness("MoulingRouge"), new Integer(2));
so in Haskell you need to explicitly wrap stuff into the ShowableInterface, in Java this wrapping is done implicitly on object creation.
credit goes to #haskell IRC for explaining this to me a year ago, or so.

Related

How to create a function that takes a list of arguments and returns a function that applies arguments to another function [duplicate]

Shouldn’t this definition be allowed in a lazy language like Haskell in which functions are curried?
apply f [] = f
apply f (x:xs) = apply (f x) xs
It’s basically a function that applies the given function to the given list of arguments and is very easily done in Lisp for example.
Are there any workarounds?
It is hard to give a static type to the apply function, since its type depends on the type of the (possibly heterogeneous) list argument. There are at least two ways one way to write this function in Haskell that I can think of:
Using reflection
We can defer type checking of the application until runtime:
import Data.Dynamic
import Data.Typeable
apply :: Dynamic -> [Dynamic] -> Dynamic
apply f [] = f
apply f (x:xs) = apply (f `dynApp` x) xs
Note that now the Haskell program may fail with a type error at runtime.
Via type class recursion
Using the semi-standard Text.Printf trick (invented by augustss, IIRC), a solution can be coded up in this style (exercise). It may not be very useful though, and still requires some trick to hide the types in the list.
Edit: I couldn't come up with a way to write this, without using dynamic types or hlists/existentials. Would love to see an example
I like Sjoerd Visscher's reply, but the extensions -- especially IncoherentInstances, used in this case to make partial application possible -- might be a bit daunting. Here's a solution that doesn't require any extensions.
First, we define a datatype of functions that know what to do with any number of arguments. You should read a here as being the "argument type", and b as being the "return type".
data ListF a b = Cons b (ListF a (a -> b))
Then we can write some (Haskell) functions that munge these (variadic) functions. I use the F suffix for any functions that happen to be in the Prelude.
headF :: ListF a b -> b
headF (Cons b _) = b
mapF :: (b -> c) -> ListF a b -> ListF a c
mapF f (Cons v fs) = Cons (f v) (mapF (f.) fs)
partialApply :: ListF a b -> [a] -> ListF a b
partialApply fs [] = fs
partialApply (Cons f fs) (x:xs) = partialApply (mapF ($x) fs) xs
apply :: ListF a b -> [a] -> b
apply f xs = headF (partialApply f xs)
For example, the sum function could be thought of as a variadic function:
sumF :: Num a => ListF a a
sumF = Cons 0 (mapF (+) sumF)
sumExample = apply sumF [3, 4, 5]
However, we also want to be able to deal with normal functions, which don't necessarily know what to do with any number of arguments. So, what to do? Well, like Lisp, we can throw an exception at runtime. Below, we'll use f as a simple example of a non-variadic function.
f True True True = 32
f True True False = 67
f _ _ _ = 9
tooMany = error "too many arguments"
tooFew = error "too few arguments"
lift0 v = Cons v tooMany
lift1 f = Cons tooFew (lift0 f)
lift2 f = Cons tooFew (lift1 f)
lift3 f = Cons tooFew (lift2 f)
fF1 = lift3 f
fExample1 = apply fF1 [True, True, True]
fExample2 = apply fF1 [True, False]
fExample3 = apply (partialApply fF1 [True, False]) [False]
Of course, if you don't like the boilerplate of defining lift0, lift1, lift2, lift3, etc. separately, then you need to enable some extensions. But you can get quite far without them!
Here is how you can generalize to a single lift function. First, we define some standard type-level numbers:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, TypeFamilies, UndecidableInstances #-}
data Z = Z
newtype S n = S n
Then introduce the typeclass for lifting. You should read the type I n a b as "n copies of a as arguments, then a return type of b".
class Lift n a b where
type I n a b :: *
lift :: n -> I n a b -> ListF a b
instance Lift Z a b where
type I Z a b = b
lift _ b = Cons b tooMany
instance (Lift n a (a -> b), I n a (a -> b) ~ (a -> I n a b)) => Lift (S n) a b where
type I (S n) a b = a -> I n a b
lift (S n) f = Cons tooFew (lift n f)
And here's the examples using f from before, rewritten using the generalized lift:
fF2 = lift (S (S (S Z))) f
fExample4 = apply fF2 [True, True, True]
fExample5 = apply fF2 [True, False]
fExample6 = apply (partialApply fF2 [True, False]) [False]
No, it cannot. f and f x are different types. Due to the statically typed nature of haskell, it can't take any function. It has to take a specific type of function.
Suppose f is passed in with type a -> b -> c. Then f x has type b -> c. But a -> b -> c must have the same type as a -> b. Hence a function of type a -> (b -> c) must be a function of type a -> b. So b must be the same as b -> c, which is an infinite type b -> b -> b -> ... -> c. It cannot exist. (continue to substitute b -> c for b)
Here's one way to do it in GHC. You'll need some type annotations here and there to convince GHC that it's all going to work out.
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE IncoherentInstances #-}
class Apply f a r | f -> a r where
apply :: f -> [a] -> r
instance Apply f a r => Apply (a -> f) a r where
apply f (a:as) = apply (f a) as
instance Apply r a r where
apply r _ = r
test = apply ((+) :: Int -> Int -> Int) [1::Int,2]
apply' :: (a -> a -> a) -> [a] -> a
apply' = apply
test' = apply' (+) [1,2]
This code is a good illustration of the differences between static and dynamic type-checking. With static type-checking, the compiler can't be sure that apply f really is being passed arguments that f expects, so it rejects the program. In lisp, the checking is done at runtime and the program might fail then.
I am not sure how much this would be helpful as I am writing this in F# but I think this can be easily done in Haskell too:
type 'a RecFunction = RecFunction of ('a -> 'a RecFunction)
let rec apply (f: 'a RecFunction) (lst: 'a list) =
match (lst,f) with
| ([],_) -> f
| ((x::xs), RecFunction z) -> apply (z x) xs
In this case the "f" in question is defined using a discriminated union which allows recursive data type definition. This can be used to solved the mentioned problem I guess.
With the help and input of some others I defined a way to achieve this (well, sort of, with a custom list type) which is a bit different from the previous answers. This is an old question, but it seems to still be visited so I will add the approach for completeness.
We use one extension (GADTs), with a list type a bit similar to Daniel Wagner's, but with a tagging function type rather than a Peano number. Let's go through the code in pieces. First we set the extension and define the list type. The datatype is polymorphic so in this formulation arguments don't have to have the same type.
{-# LANGUAGE GADTs #-}
-- n represents function type, o represents output type
data LApp n o where
-- no arguments applied (function and output type are the same)
End :: LApp o o
-- intentional similarity to ($)
(:$) :: a -> LApp m o -> LApp (a -> m) o
infixr 5 :$ -- same as :
Let's define a function that can take a list like this and apply it to a function. There is some type trickery here: the function has type n, a call to listApply will only compile if this type matches the n tag on our list type. By leaving our output type o unspecified, we leave some freedom in this (when creating the list we don't have to immediately entirely fix the kind of function it can be applied to).
-- the apply function
listApply :: n -> LApp n o -> o
listApply fun End = fun
listApply fun (p :$ l) = listApply (fun p) l
That's it! We can now apply functions to arguments stored in our list type. Expected more? :)
-- showing off the power of AppL
main = do print . listApply reverse $ "yrruC .B lleksaH" :$ End
print . listApply (*) $ 1/2 :$ pi :$ End
print . listApply ($) $ head :$ [1..] :$ End
print $ listApply True End
Unfortunately we are kind of locked in to our list type, we can't just convert normal lists to use them with listApply. I suspect this is a fundamental issue with the type checker (types end up depending on the value of a list) but to be honest I'm not entirely sure.
-- Can't do this :(
-- listApply (**) $ foldr (:$) End [2, 32]
If you feel uncomfortable about using a heterogeneous list, all you have to do is add an extra parameter to the LApp type, e.g:
-- Alternative definition
-- data FList n o a where
-- Nil :: FList o o a
-- Cons :: a -> FList f o a -> FList (a -> f) o a
Here a represents the argument type, where the function which is applied to will also have to accept arguments of all the same type.
This isn't precisely an answer to your original question, but I think it might be an answer to your use-case.
pure f <*> [arg] <*> [arg2] ...
-- example
λ>pure (\a b c -> (a*b)+c) <*> [2,4] <*> [3] <*> [1]
[7,13]
λ>pure (+) <*> [1] <*> [2]
[3]
The applicative instance of list is a lot broader than this super narrow use-case though...
λ>pure (+1) <*> [1..10]
[2,3,4,5,6,7,8,9,10,11]
-- Or, apply (+1) to items 1 through 10 and collect the results in a list
λ>pure (+) <*> [1..5] <*> [1..5]
[2,3,4,5,6,3,4,5,6,7,4,5,6,7,8,5,6,7,8,9,6,7,8,9,10]
{- The applicative instance of list gives you every possible combination of
elements from the lists provided, so that is every possible sum of pairs
between one and five -}
λ>pure (\a b c -> (a*b)+c) <*> [2,4] <*> [4,3] <*> [1]
[9,7,17,13]
{- that's - 2*4+1, 2*3+1, 4*4+1, 4*3+1
Or, I am repeating argC when I call this function twice, but a and b are
different -}
λ>pure (\a b c -> show (a*b) ++ c) <*> [1,2] <*> [3,4] <*> [" look mah, other types"]
["3 look mah, other types","4 look mah, other types","6 look mah, other types","8 look mah, other types"]
So it's not the same concept, precisely, but it a lot of those compositional use-cases, and adds a few more.

Can you do pattern matching on the type-level in Haskell?

Basically, what I want is a function that takes a function type (a -> b -> c -> ...), and returns a list of all the right-subset types of that function type, for example, lets call this function f:
x = f (a -> b -> c)
x
> [a -> b -> c, b -> c, c]
And this should work for both polymorphic types, as in my example, and on concrete function types.
This would be relatively straightforward if you could pattern match on the type-level with function types like so:
g (x -> xs) = xs
g (x) = x
used as a utility function for the construction of f above, and pattern matching over function types sort of like one would pattern match over a list.
Closed type families are what you're looking for:
{-# LANGUAGE TypeFamilies #-}
type family F a where
F (x -> xs) = xs
F x = x
To fully answer your question, we need DataKinds to get type-level lists too:
{-# LANGUAGE TypeFamilies, TypeOperators, DataKinds #-}
type family F a :: [*] where
F (x -> xs) = (x -> xs) ': (F xs)
F x = '[x]
The single quote indicates that we are using those (list) constructors at a type level.
We can see that this gives the expected result with the :kind! command in GHCi
λ> :kind! F (Int -> Float -> Double)
F (Int -> Float -> Double) :: [*]
= '[Int -> Float -> Double, Float -> Double, Double]
Note that the return kind of F is [*]. This means that in order to use these results, you will need to extract them from the list in some way. The only kind that has types that are inhabited is * (well, and #).
Untagged sum types
Regarding the full context:
You might be able to make something like an untagged sum type by making an Elem type family using the type level (==) and (||) from Data.Type.Equality and Data.Type.Bool respectively.

Mapping over a heterogenous data structure with a generic function

I'm working on an HList implementation and I'm stuck trying to implement a map function for it. I've tried a lot of different approaches but with each one I reach compiler errors related to that function.
Following is an example of how I want to use a generic function Just to apply it to all elements of the input data structure.
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
-- | An input heterogenous data structure
recursivePairs :: (Int, (Char, (Bool, ())))
recursivePairs = (1, ('a', (True, ())))
-- | This is how I want to use it
recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool, ())))
recursivePairs' = hMap Just recursivePairs
class HMap f input output where
hMap :: f -> input -> output
-- | A counterpart of a Nil pattern match for a list
instance HMap f () () where
hMap _ _ = ()
-- | A counterpart of a Cons pattern match for a list
instance
( HMap f iTail oTail,
Apply f iHead oHead ) =>
HMap f (iHead, iTail) (oHead, oTail)
where
hMap f (head, tail) = (apply f head, hMap f tail)
class Apply f input output where
apply :: f -> input -> output
instance Apply (input -> output) input output where
apply = id
With this I'm getting the following compiler error:
No instance for (Apply (a0 -> Maybe a0) Int (Maybe Int))
arising from a use of `hMap'
The type variable `a0' is ambiguous
Is there at all a way to solve this and if not then why?
The problem is that you are trying to use a polymorphic function with different arguments, but your Apply instance takes a function (a mono-type). You can easily fix this multiple ways
data JustIfy = JustIfy
instance Apply JustIfy a (Maybe a) where
apply _ = Just
recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool, ())))
recursivePairs' = hMap JustIfy recursivePairs
works with your code just fine
EDIT: A more general approach to the same thing is (requiring RankNTypes)
--A "universal" action that works on all types
newtype Univ f = Univ (forall x. x -> f x)
instance Apply (Univ f) x (f x) where
apply (Univ f) x = f x
recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool, ())))
recursivePairs' = hMap (Univ Just) recursivePairs
or if you are using a recent ish version of GHC and are willing to turn on more extensions
newtype Univ' c f = Univ' (forall x. c x => x -> f x)
instance c x => Apply (Univ' c f) x (f x) where
apply (Univ' f) x = f x
class All x
instance All x
recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool, ())))
recursivePairs' = hMap (Univ' Just :: Univ' All Maybe) recursivePairs
which is nice since then it lets you do things like include a "show" in the function you map with.
For a more general solution, check out Oleg's Type level lambda caclulus which allows you to write code at the value level and then auto-magically infers the appropriate type level program. Unfortunetly, Oleg's solution is at this point rather old, and uses a nominal implementation of the LC which I don't particularly like. I've been thinking about how to do better, but might hold off until deciable equality comes to type families.
My view is that HLists should these days be done using GADTs and DataKinds rather than tuples. Type families are preferable to functional dependencies, but currently are more limited because they lack decidable equality.
Although the following does not exactly answer the question (so I won't be accepting it), it does solve the problem concerning mapping the structure without requiring any additional instances for applicative functors:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
import Control.Applicative
main = do
print $ (hPure recursivePairs :: (Maybe Int, (Maybe Char, (Maybe Bool, ()))))
print $ (hPure recursivePairs :: ([Int], ([Char], ([Bool], ()))))
recursivePairs :: (Int, (Char, (Bool, ())))
recursivePairs = (1, ('a', (True, ())))
class HPure input output where
hPure :: input -> output
instance HPure () () where
hPure _ = ()
instance
( Applicative f,
HPure iTail oTail ) =>
HPure (iHead, iTail) (f iHead, oTail)
where hPure (iHead, iTail) = (pure iHead, hPure iTail)
Outputs:
(Just 1,(Just 'a',(Just True,())))
([1],("a",([True],())))

How can I return a non-concrete value from a function that supports some API?

I'm building an API between two models. I don't care if it returns a [] or Seq or anything Foldable is fine. But if I try to do that, I get errors.
module Main where
import Prelude hiding (foldr)
import Data.Foldable
import Data.Sequence
data Struct = Struct
main = do
print $ foldr (+) 0 $ list Struct
print $ foldr (+) 0 $ listFree Struct
listFree :: Foldable f => a -> f Int
listFree s = singleton 10
class TestClass a where
list :: Foldable f => a -> f Int
instance TestClass Struct where
list s = singleton 10
Both the listFree and the list definitions give the same error:
TestFoldable.hs:19:12:
Could not deduce (f ~ [])
from the context (Foldable f)
bound by the type signature for
list :: Foldable f => Struct -> f Int
at TestFoldable.hs:19:3-15
`f' is a rigid type variable bound by
the type signature for list :: Foldable f => Struct -> f Int
at TestFoldable.hs:19:3
In the expression: [10]
In an equation for `list': list s = [10]
In the instance declaration for `TestClass Struct'
Why is that? And what is the "right" way to accomplish what I'm trying to do here?
What I'm trying to accomplish is to hide the implementation from the caller. The actual data structure might be a Seq, IntMap, or anything else and most likely is not a list.
I'm getting responses that say "just return a list". But that means conversion, doesn't it? What if it's a 1,000,000 element structure? Converting it to an intermediate data structure just because of limitations of the API seems a poor solution.
And this is a general problem. How does one have a return value that conforms to some API? To hide the concrete implementation so the implementer is free to choose whatever structure is best for them and can change it without having to change the users of the API.
Another way of putting it is: how can I return an interface instead of a concrete type?
Closing Note:
The Haskell community on StackOverflow is (SuperlativeCompliment c => forall c. c)
Existential quantification seems like the general solution to this situation.
Another possibility to consider, which is not a general solution but might have worked for this specific case, that might avoid the extra wrapper value required by existential solution is to return a closure of the fold for the client:
list :: a -> ((Int -> b -> b) -> b -> b)
list = \f a0 -> foldr f a0 (singleton 10)
Why is that?
The type Foldable f => a -> f Int does not mean that the function might return any foldable it wants. It means that the function will return whichever type the user wants. I.e. if the user uses the function in a context where a list is required that should work and if he uses it in a context where a Seq is required that should also work. Since this is clearly not the case with your definition, it doesn't match its type.
And what is the "right" way to accomplish what I'm trying to do here?
The easiest way would be to just make your function return a list.
However if you do need to hide the fact that you're using lists from your users, the easiest way would be to create a wrapper type around the list and not export that type's constructor. I.e. something like:
module Bla (ListResult(), list) where
data ListResult a = ListResult [a]
instance Foldable (ListResult a) where
foldr op s (ListResult xs) = foldr op s xs
list s = ListResult [10]
Now if the user imports your module, it can fold over a ListResult because it's foldable, but it can't unpack it to get at the list because the constructor is not exported. So if you later change ListResult's definition to data ListResult a = ListResult (Seq a) and list to also use a Seq instead of a list, that change will be completely invisible to the user.
sepp2k already provided a good answer, but allow me to take a similar but slightly different angle. What you have done is provide result-type polymorphism. You wrote:
listFree :: Foldable f => a -> f Int
What this does is promise that you can produce any foldable that the user may need. You, of course, could never keep this promise because Foldable doesn't provide any constructor-like functions.
So what you're trying to do deals with generics. You want to make a weak promise: the function listFree will produce some Foldable, but in the future, it may change. You might implement it with a regular list today, but later, you might re-implement it with something else. And you want this implementation detail to be just that: an implementation detail. You want the contract for that function (the type signature) to remain the same.
Sounds like a job for yet another weird and confusing Haskell extension! Existential Quantification!
{-# LANGUAGE ExistentialQuantification #-}
import Prelude hiding (foldr, foldl, foldr1, foldl1)
import Data.Foldable
data SomeFoldable a = forall f. Foldable f => F (f a)
foo :: SomeFoldable Int
foo = F [1,2,3]
Here I've provide a value foo, but it has the type SomeFoldable Int. I'm not telling you which Foldable it is, simply that it is some foldable. SomeFoldable can easily be made an instance of Foldable, for convenience.
instance Foldable SomeFoldable where
fold (F xs) = fold xs
foldMap f (F xs) = foldMap f xs
foldr step z (F xs) = foldr step z xs
foldl step z (F xs) = foldl step z xs
foldr1 step (F xs) = foldr1 step xs
foldl1 step (F xs) = foldl1 step xs
Now we can do Foldable things with foo, for example:
> Data.Foldable.sum foo
6
But we can't do anything with it besides what Foldable exposes:
> print foo
No instance for (Show (SomeFoldable Int)) blah blah blah
It's easy to adapt your code to work as desired:
data Struct = Struct
main = do
print $ foldr (+) 0 $ list Struct
print $ foldr (+) 0 $ listFree Struct
listFree :: a -> SomeFoldable Int
listFree s = F [10]
class TestClass a where
list :: a -> SomeFoldable Int
instance TestClass Struct where
list s = F [10]
But remember, Existential Quantification has its drawbacks. There is no way to unwrap SomeFoldable to get the concrete Foldable underneath. The reason for this is the same reason that your function signature was wrong at the beginning: it promises result-type polymorphism: a promise it cannot keep.
unwrap :: Foldable f => SomeFoldable a -> f a -- impossible!
unwrap (F xs) = xs -- Nope. Keep dreaming. This won't work.
The Foldable class only provides methods for destructing instances of Foldable, and none for constructing instances. The complete list of class methods is reproduced below:
class Foldable t where
fold :: Monoid m => t m -> m
foldMap :: Monoid m => (a -> m) -> t a -> m
foldr :: (a -> b -> b) -> b -> t a -> b
foldl :: (a -> b -> a) -> a -> t b -> a
foldr1 :: (a -> a -> a) -> t a -> a
foldl1 :: (a -> a -> a) -> t a -> a
You can see that the return type of these methods never has a "t foo" type. So you cannot construct a value that is polymorphic in which Foldable instance you choose.
However, there are classes over type constructors for which the constructor appears in the return type of at least one method. For instance, there is
class Pointed p where
point :: a -> p a
provided by the pointed package. There is also the Monoid class provided by base:
class Monoid m where
mempty :: m
mappend :: m -> m -> m
mconcat :: [m] -> m
You could combine these two classes like so:
points :: (Pointed p, Monoid (p a)) => [a] -> p a
points = mconcat . map point
For example, in ghci:
> points [7,3,8] :: Set Int
fromList [3,7,8]
> points [7,3,8] :: First Int
First { getFirst = Just 7 }
> points [7,3,8] :: Last Int
Last { getLast = Just 8 }
> points [7,3,8] :: [Int]
[7,3,8]
> points [7,3,8] :: Seq Int
fromList [7,3,8]
etc.
As sepp2k said in his answer,
the problem is that we must have a monomorph return type.
Like a list in his answer.
However, we can still return a wrappertype that has a named type,
FoldableContainer, yet it is Foldable.
To achieve this we need GADTts.
{-# LANGUAGE GADTs #-}
module Main where
import Prelude hiding (foldr)
import Data.Foldable
data Struct = Struct
data FoldableContainer a where
F :: Foldable f => f a -> FoldableContainer a
instance Foldable FoldableContainer where
foldMap g (F f) = foldMap g f
main = do
print $ foldr (+) 0 $ list Struct
print $ foldr (+) 0 $ listFree Struct
listFree :: a -> FoldableContainer Int
listFree s = F [10]
class TestClass a where
list :: a -> FoldableContainer Int
instance TestClass Struct where
list s = F [10]
Note however that while this works it might as some say indeed be better
to just return a list. Why? First of all we create no extra type,
and second of all, each constructed F will need to carry alongside
the Foldable dictionary since it isn't known at compile time.
I don't know how much performence penalty this is but it must not be forgotten.
On the other hand we don't need lists as intermedite types anymore,
that is using sum on Set Int need not first be converted to a [Int].
The updated question has a very different answer. (Since my other answer is a good one, but answering a different question, I'm going to leave it.)
Create an abstract data type. The short of it is to define a new type in your module
newtype Struct a = Struct [a]
where here I've assumed for now that [a] is the concrete implementation that you want to hide. Then, you add a Foldable instance.
deriving instance Foldable Struct
-- could do this on the newtype definition line above,
-- but it doesn't fit with the flow of the answer
At the module boundary, you hide the actual implementation by exporting the Struct type, but not the Struct constructor. The only thing your callers will be able to do with a Struct a is call Foldable methods on it.

How can I abstract a common Haskell recursive applicative functor pattern

While using applicative functors in Haskell I've often run into situations where I end up with repetitive code like this:
instance Arbitrary MyType where
arbitrary = MyType <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
In this example I'd like to say:
instance Arbitrary MyType where
arbitrary = applyMany MyType 4 arbitrary
but I can't figure out how to make applyMany (or something similar to it). I can't even figure out what the type would be but it would take a data constructor, an Int (n), and a function to apply n times. This happens when creating instances for QuickCheck, SmallCheck, Data.Binary, Xml serialization, and other recursive situations.
So how could I define applyMany?
Check out derive. Any other good generics library should be able to do this as well; derive is just the one I am familiar with. For example:
{-# LANGUAGE TemplateHaskell #-}
import Data.DeriveTH
import Test.QuickCheck
$( derive makeArbitrary ''MyType )
To address the question you actually asked, FUZxxl is right, this is not possible in plain vanilla Haskell. As you point out, it is not clear what its type should even be. It is possible with Template Haskell metaprogramming (not too pleasant). If you go that route, you should probably just use a generics library which has already done the hard research for you. I believe it is also possible using type-level naturals and typeclasses, but unfortunately such type-level solutions are usually difficult to abstract over. Conor McBride is working on that problem.
I think you can do it with OverlappingInstances hack:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, TypeFamilies, OverlappingInstances #-}
import Test.QuickCheck
import Control.Applicative
class Arbitrable a b where
convert :: Gen a -> Gen b
instance (Arbitrary a, Arbitrable b c) => Arbitrable (a->b) c where
convert a = convert (a <*> arbitrary)
instance (a ~ b) => Arbitrable a b where
convert = id
-- Should work for any type with Arbitrary parameters
data MyType a b c d = MyType a b c d deriving (Show, Eq)
instance Arbitrary (MyType Char Int Double Bool) where
arbitrary = convert (pure MyType)
check = quickCheck ((\s -> s == s) :: (MyType Char Int Double Bool -> Bool))
Not satisfied with my other answer, I have come up with an awesomer one.
-- arb.hs
import Test.QuickCheck
import Control.Monad (liftM)
data SimpleType = SimpleType Int Char Bool String deriving(Show, Eq)
uncurry4 f (a,b,c,d) = f a b c d
instance Arbitrary SimpleType where
arbitrary = uncurry4 SimpleType `liftM` arbitrary
-- ^ this line is teh pwnzors.
-- Note how easily it can be adapted to other "simple" data types
ghci> :l arb.hs
[1 of 1] Compiling Main ( arb.hs, interpreted )
Ok, modules loaded: Main.
ghci> sample (arbitrary :: Gen SimpleType)
>>>a bunch of "Loading package" statements<<<
SimpleType 1 'B' False ""
SimpleType 0 '\n' True ""
SimpleType 0 '\186' False "\208! \227"
...
Lengthy explanation of how I figured this out
So here's how I got it. I was wondering, "well how is there already an Arbitrary instance for (Int, Int, Int, Int)? I'm sure no one wrote it, so it must be derived somehow. Sure enough, I found the following in the docs for instances of Arbitrary:
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d) => Arbitrary (a, b, c, d)
Well, if they already have that defined, then why not abuse it? Simple types that are merely composed of smaller Arbitrary data types are not much different than just a tuple.
So now I need to somehow transform the "arbitrary" method for the 4-tuple so that it works for my type. Uncurrying is probably involved.
Stop. Hoogle time!
(We can easily define our own uncurry4, so assume we already have this to operate with.)
I have a generator, arbitrary :: Gen (q,r,s,t) (where q,r,s,t are all instances of Arbitrary). But let's just say it's arbitrary :: Gen a. In other words, a represents (q,r,s,t). I have a function, uncurry4, which has type (q -> r -> s -> t -> b) -> (q,r,s,t) -> b. We are obviously going to apply uncurry4 to our SimpleType constructor. So uncurry4 SimpleType has type (q,r,s,t) -> SimpleType. Let's keep the return value generic, though, because Hoogle doesn't know about our SimpleType. So remembering our definition of a, we have essentially uncurry4 SimpleType :: a -> b.
So I've got a Gen a and a function a -> b. And I want a Gen b result. (Remember, for our situation, a is (q,r,s,t) and b is SimpleType). So I am looking for a function with this type signature: Gen a -> (a -> b) -> Gen b. Hoogling that, and knowing that Gen is an instance of Monad, I immediately recognize liftM as the monadical-magical solution to my problems.
Hoogle saves the day again. I knew there was probably some "lifting" combinator to get the desired result, but I honestly didn't think to use liftM (durrr!) until I hoogled the type signature.
Here is what I'v got at least:
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module ApplyMany where
import Control.Applicative
import TypeLevel.NaturalNumber -- from type-level-natural-number package
class GetVal a where
getVal :: a
class Applicative f => ApplyMany n f g where
type Res n g
app :: n -> f g -> f (Res n g)
instance Applicative f => ApplyMany Zero f g where
type Res Zero g = g
app _ fg = fg
instance
(Applicative f, GetVal (f a), ApplyMany n f g)
=> ApplyMany (SuccessorTo n) f (a -> g)
where
type Res (SuccessorTo n) (a -> g) = Res n g
app n fg = app (predecessorOf n) (fg<*>getVal)
Usage example:
import Test.QuickCheck
data MyType = MyType Char Int Bool deriving Show
instance Arbitrary a => GetVal (Gen a) where getVal = arbitrary
test3 = app n3 (pure MyType) :: Gen MyType
test2 = app n2 (pure MyType) :: Gen (Bool -> MyType)
test1 = app n1 (pure MyType) :: Gen (Int -> Bool -> MyType)
test0 = app n0 (pure MyType) :: Gen (Char -> Int -> Bool -> MyType)
Btw, I think this solution is not very useful in real world. Especially without local type-classes.
Check out liftA2 and liftA3. Also, you can easily write your own applyTwice or applyThrice methods like so:
applyTwice :: (a -> a -> b) -> a -> b
applyTwice f x = f x x
applyThrice :: (a -> a -> a -> b) -> a -> b
applyThrice f x = f x x x
There's no easy way I can see to get the generic applyMany you're asking for, but writing trivial helpers such as these is neither difficult nor uncommon.
[edit] So it turns out, you'd think something like this would work
liftA4 f a b c d = f <$> a <*> b <*> c <*> d
quadraApply f x = f x x x x
data MyType = MyType Int String Double Char
instance Arbitrary MyType where
arbitrary = (liftA4 MyType) `quadraApply` arbitrary
But it doesn't. (liftA4 MyType) has a type signature of (Applicative f) => f Int -> f String -> f Double -> f Char -> f MyType. This is incompatible with the first parameter of quadraApply, which has a type signature of (a -> a -> a -> a -> b) -> a -> b. It would only work for data structures that hold multiple values of the same Arbitrary type.
data FourOf a = FourOf a a a a
instance (Arbitrary a) => Arbitrary (FourOf a) where
arbitrary = (liftA4 FourOf) `quadraApply` arbitrary
ghci> sample (arbitrary :: Gen (FourOf Int))
Of course you could just do this if you had that situation
ghci> :l +Control.Monad
ghci> let uncurry4 f (a, b, c, d) = f a b c d
ghci> samples <- sample (arbitrary :: Gen (Int, Int, Int, Int))
ghci> forM_ samples (print . uncurry4 FourOf)
There might be some language pragma that can shoehorn the "arbitrary" function into the more diverse data types. But that's currently beyond my level of Haskell-fu.
This is not possible with Haskell. The problem is, that your function will have a type, that depends on the numeric argument. With a type system that allows dependent types, that should be possible, but I guess not in Haskell.
What you can try is using polymorphism and tyeclasses to archieve this, but it could become hacky and you need a big bunch of extensions to satisfy the compiler.

Resources