score:5
short answer.
in haskell there are no implicit conversions. also there are no union types - only disjoint unions(which are algebraic data types). so you can only write:
somelist :: [intorchar]
somelist = [in 1, ch 'c']
longer and certainly not gentle answer.
note: this is a technique that's very rarely used. if you need it you're probably overcomplicating your api.
there are however existential types.
{-# language existentialquantification, rankntypes #-}
class intorchar a where
intorchar :: a -> either int char
instance intorchar int where
intorchar = left
instance intorchar char where
intorchar = right
data list = nil
| forall a. (intorchar a) => cons a list
somelist :: list
somelist = (1 :: int) `cons` ('c' `cons` nil)
here i have created a typeclass intorchar
with only function intorchar
. this way you can convert anything of type forall a. (intorchar a) => a
to either int char
.
and also a special kind of list that uses existential type in its second constructor.
here type variable a
is bound(with forall
) at the constructor scope. therefore every time
you use cons
you can pass anything of type forall a. (intorchar a) => a
as a first argument. consequently during a destruction(i.e. pattern matching) the first argument will
still be forall a. (intorchar a) => a
. the only thing you can do with it is either pass it on or call intorchar
on it and convert it to either int char
.
withhead :: (forall a. (intorchar a) => a -> b) -> list -> maybe b
withhead f nil = nothing
withhead f (cons x _) = just (f x)
intorchartostring :: (intorchar a) => a -> string
intorchartostring x =
case intorchar of
left i -> show i
right c -> show c
somelistheadstring :: maybe string
somelistheadstring = withhead intorchartostring somelist
again note that you cannot write
{- wont compile
safehead :: intorchar a => list -> maybe a
safehead nil = nothing
safehead (cons x _) = just x
-}
-- this will
safehead2 :: list -> maybe (either int char)
safehead2 nil = nothing
safehead2 (cons x _) = just (intorchar x)
safehead
will not work because you want a type of intorchar a => maybe a
with a
bound at safehead
scope and just x
will have a type of intorchar a1 => maybe a1
with a1
bound at cons
scope.
score:2
i think that the distinction that is being made here is that your algebraic data type intorchar
is a "tagged union" - that is, when you have a value of type intorchar
you will know if it is an int
or a char
.
by comparison consider this anonymous union definition (in c):
typedef union { char c; int i; } intorchar;
if you are given a value of type intorchar
you don't know (apriori) which selector is valid. that's why most of the time the union
constructor is used in conjunction with a struct
to form a tagged-union construction:
typedef struct {
int tag;
union { char c; int i; } intorchar_u
} intorchar;
here the tag
field encodes which selector of the union is valid.
the other major use of the union
constructor is to overlay two structures to get an efficient mapping between sub-structures. for example, this union is one way to efficiently access the individual bytes of a int (assuming 8-bit chars and 32-bit ints):
union { char b[4]; int i }
now, to illustrate the main difference between "tagged unions" and "anonymous unions" consider how you go about defining a function on these types.
to define a function on an intorchar
value (the tagged union) i claim you need to supply two functions - one which takes an int
(in the case that the value is an int
) and one which takes a char
(in case the value is a char
). since the value is tagged with its type, it knows which of the two functions it should use.
if we let f(a,b)
denote the set of functions from type a
to type b
, we have:
f(intorchar,b) = f(int,b) \times f(char,b)
where \times
denotes the cross product.
as for the anonymous union intorchar
, since a value doesn't encode anything bout its type the only functions which can be applied are those which are valid for both int
and char
values, i.e.:
f(intorchar,b) = f(int,b) \cap f(char,b)
where \cap
denotes intersection.
in haskell there is only one function (to my knowledge) which can be applied to both integers and chars, namely the identity function. so there's not much you could do with a list like [2, 'b']
in haskell. in other languages this intersection may not be empty, and then constructions like this make more sense.
to summarize, you can have integers and characters in the same list if you create a tagged-union, and in that case you have to tag each of the values which will make you list look like:
[ i 2, c 'b', ... ]
if you don't tag your values then you are creating something akin to an anonymous union, but since there aren't any (useful) functions which can be applied to both integers and chars there's not really anything you can do with that kind of union.
score:3
in scala there are types that include both int
and char
such as anyval
and any
, which are both supertypes of char
and int
. in haskell there is no such hierarchy, and all the basic types are disjoint.
you can create your own union types which describe the concept of 'either an int
or a char
(or you could use the built-in either
type), but there are no implicit conversions in haskell to transparently convert an int
into an intorchar
.
you could emulate the concept of 'any' using existential types:
data anybox = forall a. (show a, hashable a) => ab a
heterolist :: [anybox]
heterolist = [ab (1::int), ab 'b']
showwithhash :: anybox -> string
showwithhash (ab v) = show v ++ " - " ++ (show . hash) v
let strs = map showwithhash heterolist
be aware that this pattern is discouraged however.
Source: stackoverflow.com
Related Query
- Gentle Intro to Haskell: " .... there is no single type that contains both 2 and 'b'." Can I not make such a type ?
- Is there a division operation that produces both quotient and reminder?
- Scala Puzzle: enforcing that two function arguments are of the same type AND both are a subtype of a given class
- Is there a C-like mini-syntax/language that can be both translated to native C/C++ and Java?
- How do I create a Map type that allows multiple types for both keys and values?
- Is there a function that transforms/maps both Either's Left and Right cases taking two transformation functions respectively?
- Writing a single implicit class for both a value and a functor of that value
- Scala function that requires a type that extends both a class and a trait
- Is there any smart implementation of flatMap that is able to infer common type characteristics for its input and output?
- What are the differences and similarities of Scala and Haskell type systems?
- Spark: is there a way to print out classpath of both spark-shell and spark?
- Common naming conventions for option type variables and methods that return them
- Is there a "SELF" type in scala that represents the current type?
- Liftweb: create a form that can be submitted both traditionally and with AJAX
- Using SBT to manage projects that contain both Scala and Python
- Is there a specs matcher that will unbox Option and Either
- Is there any consideration for maven project and sbt project and play framework to share one single repository?
- (In Scala,) Is there anything that can be done with generic type parameters of classes but not with abstract type members?
- Generic function that accepts two monadic values and returns a single monadic value
- Is there a way to call a function defined using `val` in Scala with the whole curly brace block as an argument and not the final result of that block?
- Generic implicit class that applies both to Int and Long
- Scala type inference for both a generic type and it's type parameter - why doesn't it work?
- Valid type casting of both covariant and contravariant class at runtime in Scala
- IntelliJ IDEA : support both SBT and Maven on a single project
- Is there any method that does the same thing as map() but generates a different type of container?
- Method returns NodeBuffer instead of Elem and that violates the type checking rule
- Scala type that is Iterable and has a length?
- Cannot call a function that accepts and returns an object of a self-referential parametrised type in a trait
- Can I use a single Play WebSocket for both broadcasting and private messages?
- Is there are way to create a generic class with a trait or mixin that is a subtype of the type parameter
More Query from same tag
- ant does not expand my scala home directory
- Group values by a key with any Monoid
- Scala HashMap from an Array
- Scala: Mixing traits with private fields
- How would I implement an Interceptor/Filter in play framework 2.4.3 (Scala)
- How read and wrtie text files by spark with parittions?
- Rewriting a sequence by partitioning and collapsing
- How can I log in Play Framework using Scala?
- Should I use akka.http.scaladsl.util.FastFuture instead of scala.concurrent.Future?
- Get the Unicode when an emoji is provided as input using scala
- java.lang.IllegalArgumentException: Scrapped or attached views may not be recycled. isScrap:false isAttached:true
- Joining data in Scala using array_contains() method
- scala-js unexpected checks resulting to undefined behavior
- Multiple nullValues in spark csv
- Euclidean distance in spark 2.1
- Scala error: value $ is not a member of object org.apache.spark.api.java.JavaSparkContext
- Using scala to accumulate elementwise sums
- Is there any way to perform a side-effect within a future chain, without changing the value propagation
- Rename and Move S3 files based on their folders name in spark scala
- object mongodb is not a member of package com
- Is there any special support for environment variable access in Ammonite?
- Create list from command line args in Scala
- Are actors the right tool to implement the messaging between a simple multiplayer game?
- Ivy Indirect Dependency Listed Twice
- Scala 2.10 TypeTag usage
- Transform data in spark scala column to row
- how to resolve akka.stream.Graph sink error akka stream using akka typed
- scala play 2.1.1 json functional syntax mapping data to a different format
- SORM: How can I use Sorm in Scala 2.11.6
- How to provide Java callbacks (with 'void' return type), to Scala?