cannot show result from an instance function in haskell - class

class (Eq k, Ord k, Show k) => KEY k where
keyBuild :: NumId -> NumId -> NumId -> k
keyDummy :: k
keyFromList :: [NumId] -> k
-- keyGenerate :: (DATAPOOL p) => p -> Int -> [k] -- p = Pool k e s
newtype PrimaryKey = PK (NumId, NumId, NumId) deriving (Eq, Ord, Show)
instance KEY PrimaryKey where
keyBuild k0 k1 k2 = PK (k0,k1,k2)
keyDummy = PK (0,0,0)
keyFromList is = keyFromList (take 3 (is ++ (replicate 3 0)))
keyGenerate p cnt = let
ks = keys p
pks = map (\l -> keyFromList (randomize l)) (replicate cnt 3)
in pks
in ghci I do
let k1 = keyBuild 1 2 3
let k2 = PK (1,2,3)
k1 == k2
True
k2
PK (1,2,3)
and get True and the value of k2 as expected, but
k1
231:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘it’
prevents the constraint ‘(KEY a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instance exist:
instance [safe] KEY PrimaryKey -- Defined at Work
Expected PK(1,2,3)
PrimaryKey has deriving (Eq, Ord, Show) so what have I done wrong or missed?

You have not given k1 a fixed type. Because keyBuild can construct a key of any type with the right instance, it has the polymorphic type k1 :: KEY k => k. That's nice because you can then compare k1 to keys of different concrete types... in your case, you've tried it with k2 :: PrimaryKey, but you could just as well do k1 == k3 with k3 :: SomeOtherKeyType, provided SomeOtherKeyType is also an instance of the KEY class – in that case, k1 would simply also “take over” the type SomeOtherKeyType.
The flip side is that k1 has no particular type. It may in fact be any applicable type, but how is the compiler supposed to know which you want? When using == it must be the same type on both sides, so there it's sufficient to have a concrete type on one side, but all by itself k1 is ambiguous.
It so happens that in your module there is only one instance that matches, namely KEY PrimaryKey but in general there would be many (or zero!) such instances. It would be strange if the compiler just picked one arbitrarily, wouldn't it?
So if you want to show k1, you need to manually pick one type. Easy enough to do, just add a local signature:
*Main> let k1 = keyBuild 1 2 3
*Main> :t k1
k1 :: KEY k => k
*Main> k1 :: PrimaryKey
PK (1,2,3)

Related

Combining lists of variants of different types in purescript

I have been playing around with Purescript as a means of experimenting with programming in a Haskell-like language with row and column polymorphism.
In particular, using Purescript's variant package, I was trying to write an operation to combine two lists list of "notes" sequentially, where the two lists have possibly disjoint sets of variants. The idea here is to allow users to be able to combine scores declared on some sub-set of notes to be automatically combined with scores containing a super-set, without preforming any explicit conversions.
For example, given the following boilerplate to make working with the variants easier:
import Data.Variant
import Prim.Row
data A = A
data B = B
data C = C
data D = D
data E = E
data F = F
data G = G
data H = H
_A = SProxy :: SProxy "_A"
_B = SProxy :: SProxy "_B"
_C = SProxy :: SProxy "_C"
_D = SProxy :: SProxy "_D"
_E = SProxy :: SProxy "_E"
_F = SProxy :: SProxy "_F"
_G = SProxy :: SProxy "_G"
I can define the following types:
type CNatural = Variant (
_A :: A,
_B :: B,
_C :: C,
_D :: D,
_E :: E,
_F :: F,
_G :: G)
type CPentatonic = Variant (
_A :: A,
_C :: C,
_D :: D,
_E :: E,
_G :: G)
And given those, I can define two scores:
score1 :: Array CPentatonic
score1 = [inj _A A,inj _C C]
score2 :: Array CNatural
score2 = [inj _C C, inj _B B]
So, to combine them, I want a function of signature
combine :: forall v w u. Union w v u =>
Array (Variant v)
-> Array (Variant w)
-> Array (Variant u)
However, my attempt at this:
combine x y = (map expand x) <> (map expand y)
yields
No type class instance was found for
Prim.Row.Union v2
t3
u4
The instance head contains unknown type variables. Consider adding a type annotation.
If I try changing the Union v w u constraint to a Union w v u constraint, the error goes back and forth between the first map expand, and the second map expand, but nothing I do seems to resolve both constraints, even if I have both a Union v w u and a Union w v u constraint, which I thought would have been redundant.
Is there something I'm missing? Is it possible to do something like this in Purescript using the variant library?
If you want to produce Variant u by using expand you have to require that both v and w are subrows of u:
module Main where
import Prelude
import Data.Variant (expand, Variant)
import Prim.Row (class Union)
combine :: forall v v_ w w_ u. Union w w_ u => Union v v_ u =>
Array (Variant v)
-> Array (Variant w)
-> Array (Variant u)
combine arr1 arr2 = map expand arr1 <> map expand arr2
Here is a working gist loaded into try.purescript.

Purescript: Could not match type

In the REPL this works:
> mm n = (\n -> n * 2) <$> n
> mm (2:3:Nil)
(4 : 6 : Nil)
in a file this compiles and I can run it:
squareOf ls =
map (\n -> n * n) ls
however when I add a type definition to that function
squareOf :: List Int -> Int
squareOf ls =
map (\n -> n * n) ls
I get an error:
Could not match type
List Int
with type
Int
while checking that type t0 t1
is at least as general as type Int
while checking that expression (map (\n ->
(...) n
)
)
ls
has type Int
in value declaration squareOf
where t0 is an unknown type
t1 is an unknown type
I tried changing the signature to a type alias of the list, and also I tried a forall definition with no luck.
If I inspect the definition created when I don't put signatures in my function I get:
forall t2 t3. Functor t2 => Semiring t3 => t2 t3 -> t2 t3
Can anyone explain why my signature is incorrect and also why am I getting this signature for the function?
Cheers
Edit: Thanks for the comments, updating the fn definition so it returns a List Int as well, and , of course it solves the problem
Assuming you're repl function is the behaviour you're after, you've missed out the map operator (<$>) in your later definitions.
Your repl function (with variables renamed for clarity) has the type:
mm :: forall f. Functor f => f Int -> f Int
mm ns = (\n -> n * 2) <$> ns
Which is to say: mm maps "times two" to something that is mappable" (i.e. a Functor)
Aside: you could be more concise/clear in your definition here:
mm :: forall f. Functor f => f Int -> f Int
mm = map (_*2)
This is similar to your squareOf definition, only now you're squaring so your use of (*) is more general:
squareOf :: forall f. Functor f => Semiring n => f n -> f n
squareOf = map \n -> n * n
Because (*) is a member of the Semiring typeclass.
But the signature you gave it suggests you're after some kind of fold? Let me know what output you expect from your squareOf function and I'll update the answer accordingly.
Here is map:
class Functor f where
map :: forall a b. (a -> b) -> f a -> f b
Narrowing to List Int and Int -> Int, the compiler infers
map :: (Int -> Int) -> List Int -> List Int
So, in squareOf, the expression reduces to a list of integers, not an integer. That is why the compiler complains.

Haskell - Could not deduce ... from Context error - OpenGL AsUniform class type

I'm working on making my data types general instead of taking in the OpenGL type GLfloat. So I started making it take in type a and then just replacing everything with that.
Now, I've come to a point where I'm setting uniform variables, but they take in GLfloat's. I'm using a library called GLUtil which makes it a bit easier, which has provided a class AsUniform, to check whether the type can be a uniform variable or not. I stick it in my type signature, but it stills gives me an error. Here's the code:
-- | Sets the modelview and projection matrix uniform variables.
mvpUnif :: (GL.UniformComponent a, Num a, Epsilon a, Floating a, AsUniform a) => (GLState a) -> ShaderProgram -> IO ()
mvpUnif state p = do
-- Check if view and projection matrices are there, else set them to the identity.
let vMat = case vMatrix state of
Just v -> v
Nothing -> getIdentity
let pMat = case pMatrix state of
Just p -> p
Nothing -> getIdentity
-- Multiply model and view matrix together.
let mvMatrix = vMat !*! mMatrix state
setUniform p uModelViewMatrixVar mvMatrix
setUniform p uProjectionMatrixVar pMat
and the error:
Could not deduce (AsUniform (V4 (V4 a)))
arising from a use of `setUniform'
from the context (GL.UniformComponent a,
Num a,
Epsilon a,
Floating a,
AsUniform a)
bound by the type signature for
mvpUnif :: (GL.UniformComponent a, Num a, Epsilon a, Floating a
,
AsUniform a) =>
GLState a -> ShaderProgram -> IO ()
at src\Graphics\FreeD\Shaders\DefaultShaders.hs:194:12-119
In a stmt of a 'do' block:
setUniform p uModelViewMatrixVar mvMatrix
In the expression:
do { let vMat = ...;
let pMat = ...;
let mvMatrix = vMat !*! mMatrix state;
setUniform p uModelViewMatrixVar mvMatrix;
.... }
In an equation for `mvpUnif':
mvpUnif state p
= do { let vMat = ...;
let pMat = ...;
let mvMatrix = ...;
.... }
V4 is made an instance of AsUniform, as well as M44, which is a type for (V4 (V4 a)), which I thought might be the issue, so I'm not sure why it's acting up.
Here's the source for the class:
http://hackage.haskell.org/package/GLUtil-0.8.5/docs/Graphics-GLUtil-Linear.html
Thanks!
Try adding -XFlexibleContexts and the constraint, literally, to your existing answer:
{-# LANGUAGE FlexibleContexts #-}
mvpUnif :: ( GL.UniformComponent a
, Num a
, Epsilon a
, Floating a
, AsUniform a
, AsUniform (V4 (V4 a))
) => (GLState a) -> ShaderProgram -> IO ()
Usually this is the routine for constraints that aren't inferrable, or where constraints need to be transitively included in all call sites. This happens to me all the time with MonadState et al. In this case, setUniform is the culprit.

Write this Scala Matrix multiplication in Haskell [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can you overload + in haskell?
Can you implement a Matrix class and an * operator that will work on two matrices?:
scala> val x = Matrix(3, 1,2,3,4,5,6)
x: Matrix =
[1.0, 2.0, 3.0]
[4.0, 5.0, 6.0]
scala> x*x.transpose
res0: Matrix =
[14.0, 32.0]
[32.0, 77.0]
and just so people don't say that it's hard, here is the Scala implementation (courtesy of Jonathan Merritt):
class Matrix(els: List[List[Double]]) {
/** elements of the matrix, stored as a list of
its rows */
val elements: List[List[Double]] = els
def nRows: Int = elements.length
def nCols: Int = if (elements.isEmpty) 0
else elements.head.length
/** all rows of the matrix must have the same
number of columns */
require(elements.forall(_.length == nCols))
/* Add to each elem of matrix */
private def addRows(a: List[Double],
b: List[Double]):
List[Double] =
List.map2(a,b)(_+_)
private def subRows(a: List[Double],
b: List[Double]):List[Double] =
List.map2(a,b)(_-_)
def +(other: Matrix): Matrix = {
require((other.nRows == nRows) &&
(other.nCols == nCols))
new Matrix(
List.map2(elements, other.elements)
(addRows(_,_))
)
}
def -(other: Matrix): Matrix = {
require((other.nRows == nRows) &&
(other.nCols == nCols))
new Matrix(
List.map2(elements, other.elements)
(subRows(_,_))
)
}
def transpose(): Matrix = new Matrix(List.transpose(elements))
private def dotVectors(a: List[Double],
b: List[Double]): Double = {
val multipliedElements =
List.map2(a,b)(_*_)
(0.0 /: multipliedElements)(_+_)
}
def *(other: Matrix): Matrix = {
require(nCols == other.nRows)
val t = other.transpose()
new Matrix(
for (row <- elements) yield {
for (otherCol <- t.elements)
yield dotVectors(row, otherCol)
}
)
override def toString(): String = {
val rowStrings =
for (row <- elements)
yield row.mkString("[", ", ", "]")
rowStrings.mkString("", "\n", "\n")
}
}
/* Matrix constructor from a bunch of numbers */
object Matrix {
def apply(nCols: Int, els: Double*):Matrix = {
def splitRowsWorker(
inList: List[Double],
working: List[List[Double]]):
List[List[Double]] =
if (inList.isEmpty)
working
else {
val (a, b) = inList.splitAt(nCols)
splitRowsWorker(b, working + a)
}
def splitRows(inList: List[Double]) =
splitRowsWorker(inList, List[List[Double]]())
val rows: List[List[Double]] =
splitRows(els.toList)
new Matrix(rows)
}
}
EDIT I understood that strictly speaking the answer is No: overloading * is not possible without side-effects of defining also a + and others or special tricks. The numeric-prelude package describes it best:
In some cases, the hierarchy is not finely-grained enough: Operations
that are often defined independently are lumped together. For
instance, in a financial application one might want a type "Dollar",
or in a graphics application one might want a type "Vector". It is
reasonable to add two Vectors or Dollars, but not, in general,
reasonable to multiply them. But the programmer is currently forced to
define a method for '(*)' when she defines a method for '(+)'.
It'll be perfectly safe with a smart constructor and stored dimensions. Of course there are no natural implementations for the operations signum and fromIntegral (or maybe a diagonal matrix would be fine for the latter).
module Matrix (Matrix(),matrix,matrixTranspose) where
import Data.List (transpose)
data Matrix a = Matrix {matrixN :: Int,
matrixM :: Int,
matrixElems :: [[a]]}
deriving (Show, Eq)
matrix :: Int -> Int -> [[a]] -> Matrix a
matrix n m vals
| length vals /= m = error "Wrong number of rows"
| any (/=n) $ map length vals = error "Column length mismatch"
| otherwise = Matrix n m vals
matrixTranspose (Matrix m n vals) = matrix n m (transpose vals)
instance Num a => Num (Matrix a) where
(+) (Matrix m n vals) (Matrix m' n' vals')
| m/=m' = error "Row number mismatch"
| n/=n' = error "Column number mismatch"
| otherwise = Matrix m n (zipWith (zipWith (+)) vals vals')
abs (Matrix m n vals) = Matrix m n (map (map abs) vals)
negate (Matrix m n vals) = Matrix m n (map (map negate) vals)
(*) (Matrix m n vals) (Matrix n' p vals')
| n/=n' = error "Matrix dimension mismatch in multiplication"
| otherwise = let tvals' = transpose vals'
dot x y = sum $ zipWith (*) x y
result = map (\col -> map (dot col) tvals') vals
in Matrix m p result
Test it in ghci:
*Matrix> let a = matrix 3 2 [[1,0,2],[-1,3,1]]
*Matrix> let b = matrix 2 3 [[3,1],[2,1],[1,0]]
*Matrix> a*b
Matrix {matrixN = 3, matrixM = 3, matrixElems = [[5,1],[4,2]]}
Since my Num instance is generic, it even works for complex matrices out of the box:
Prelude Data.Complex Matrix> let c = matrix 2 2 [[0:+1,1:+0],[5:+2,4:+3]]
Prelude Data.Complex Matrix> let a = matrix 2 2 [[0:+1,1:+0],[5:+2,4:+3]]
Prelude Data.Complex Matrix> let b = matrix 2 3 [[3:+0,1],[2,1],[1,0]]
Prelude Data.Complex Matrix> a
Matrix {matrixN = 2, matrixM = 2, matrixElems = [[0.0 :+ 1.0,1.0 :+ 0.0],[5.0 :+ 2.0,4.0 :+ 3.0]]}
Prelude Data.Complex Matrix> b
Matrix {matrixN = 2, matrixM = 3, matrixElems = [[3.0 :+ 0.0,1.0 :+ 0.0],[2.0 :+ 0.0,1.0 :+ 0.0],[1.0 :+ 0.0,0.0 :+ 0.0]]}
Prelude Data.Complex Matrix> a*b
Matrix {matrixN = 2, matrixM = 3, matrixElems = [[2.0 :+ 3.0,1.0 :+ 1.0],[23.0 :+ 12.0,9.0 :+ 5.0]]}
EDIT: new material
Oh, you want to just override the (*) function without any Num stuff. That's possible to o but you'll have to remember that the Haskell standard library has reserved (*) for use in the Num class.
module Matrix where
import qualified Prelude as P
import Prelude hiding ((*))
import Data.List (transpose)
class Multiply a where
(*) :: a -> a -> a
data Matrix a = Matrix {matrixN :: Int,
matrixM :: Int,
matrixElems :: [[a]]}
deriving (Show, Eq)
matrix :: Int -> Int -> [[a]] -> Matrix a
matrix n m vals
| length vals /= m = error "Wrong number of rows"
| any (/=n) $ map length vals = error "Column length mismatch"
| otherwise = Matrix n m vals
matrixTranspose (Matrix m n vals) = matrix n m (transpose vals)
instance P.Num a => Multiply (Matrix a) where
(*) (Matrix m n vals) (Matrix n' p vals')
| n/=n' = error "Matrix dimension mismatch in multiplication"
| otherwise = let tvals' = transpose vals'
dot x y = sum $ zipWith (P.*) x y
result = map (\col -> map (dot col) tvals') vals
in Matrix m p result
a = matrix 3 2 [[1,2,3],[4,5,6]]
b = a * matrixTranspose
Testing in ghci:
*Matrix> b
Matrix {matrixN = 3, matrixM = 3, matrixElems = [[14,32],[32,77]]}
There. Now if a third module wants to use both the Matrix version of (*) and the Prelude version of (*) it'll have to of course import one or the other qualified. But that's just business as usual.
I could've done all of this without the Multiply type class but this implementation leaves our new shiny (*) open for extension in other modules.
Alright, there's a lot of confusion about what's happening here floating around, and it's not being helped by the fact that the Haskell term "class" does not line up with the OO term "class" in any meaningful way. So let's try to make a careful answer. This answer starts with Haskell's module system.
In Haskell, when you import a module Foo.Bar, it creates a new set of bindings. For each variable x exported by the module Foo.Bar, you get a new name Foo.Bar.x. In addition, you may:
import qualified or not. If you import qualified, nothing more happens. If you do not, an additional name without the module prefix is defined; in this case, just plain old x is defined.
change the qualification prefix or not. If you import as Alias, then the name Foo.Bar.x is not defined, but the name Alias.x is.
hide certain names. If you hide name foo, then neither the plain name foo nor any qualified name (like Foo.Bar.foo or Alias.foo) is defined.
Furthermore, names may be multiply defined. For example, if Foo.Bar and Baz.Quux both export the variable x, and I import both modules without qualification, then the name x refers to both Foo.Bar.x and Baz.Quux.x. If the name x is never used in the resulting module, this clash is ignored; otherwise, a compiler error asks you to provide more qualification.
Finally, if none of your imports mention the module Prelude, the following implicit import is added:
import Prelude
This imports the Prelude without qualification, with no additional prefix, and without hiding any names. So it defines "bare" names and names prefixed by Prelude., and nothing more.
Here ends the bare basics you need to understand about the module system. Now let's discuss the bare basics you need to understand about typeclasses.
A typeclass includes a class name, a list of type variables bound by that class, and a collection of variables with type signatures that refer to the bound variables. Here's an example:
class Foo a where
foo :: a -> a -> Int
The class name is Foo, the bound type variable is a, and there is only one variable in the collection, namely foo, with type signature a -> a -> Int. This class declares that some types have a binary operation, named foo, which computes an Int. Any type may later (even in another module) be declared to be an instance of this class: this involves defining the binary operation above, where the bound type variable a is substituted with the type you are creating an instance for. As an example, we might implement this for integers by the instance:
instance Foo Int where
foo a b = (a `mod` 76) * (b + 7)
Here ends the bare basics you need to understand about typeclasses. We may now answer your question. The only reason the question is tricky is because it falls smack dab on the intersection between two name management techniques: modules and typeclasses. Below I discuss what this means for your specific question.
The module Prelude defines a typeclass named Num, which includes in its collection of variables a variable named *. Therefore, we have several options for the name *:
If the type signature we desire happens to follow the pattern a -> a -> a, for some type a, then we may implement the Num typeclass. We therefore extend the Num class with a new instance; the name Prelude.* and any aliases for this name are extended to work for the new type. For matrices, this would look like, for example,
instance Num Matrix where
m * n = {- implementation goes here -}
We may define a different name than *.
m |*| n = {- implementation goes here -}
We may define the name *. Whether this name is defined as part of a new type class or not is immaterial. If we do nothing else, there will then be at least two definitions of *, namely, the one in the current module and the one implicitly imported from the Prelude. We have a variety of ways of dealing with this. The simplest is to explicitly import the Prelude, and ask for the name * not to be defined:
import Prelude hiding ((*))
You might alternately choose to leave the implicit import of Prelude, and use a qualified * everywhere you use it. Other solutions are also possible.
The main point I want you to take away from this is: the name * is in no way special. It is just a name defined by the Prelude, and all of the tools we have available for namespace control are available.
You can implement * as matrix multiplication by defining an instance of Num class for Matrix. But the code won't be type-safe: * (and other arithmetic operations) on matrices as you define them is not total, because of size mismatch or in case of '/' non-existence of inverse matrices.
As for 'the hierarchy is not defined precisely' - there is also Monoid type class, exactly for the cases when only one operation is defined.
There are too many things to be 'added', sometimes in rather exotic ways (think of permutation groups). Haskell designers designed to reserve arithmetical operations for different representations of numbers, and use other names for more exotic cases.

Can this functionality be implemented with Haskell's type system?

In Scala, the higher order operations on collections always return the best possible type in the context. For example, in case of BitSet, if you map ints to ints you get a BitSet, but if you map ints to strings, you get a general Set. Similarly, if you map a Map with a function that yields a pair, then you get a Map in return. Else you get a simple Iterable. Both the static type and the runtime representation of map's result depend on the result type of the function that's passed to it.
scala> Map(2 -> 'a', 6 -> 'b') map { case (k, v) => (k + 1, v.toString) }
res0: scala.collection.immutable.Map[Int,java.lang.String] = Map(3 -> a, 7 -> b)
scala> Map(2 -> 'a', 6 -> 'b') map { _._1 }
res1: scala.collection.immutable.Iterable[Int] = List(2, 6)
scala> import collection.immutable.BitSet
import collection.immutable.BitSet
scala> BitSet(2, 44, 93).map(1 +)
res3: scala.collection.immutable.BitSet = BitSet(3, 45, 94)
scala> BitSet(2, 44, 93).map(_ + "hola")
res4: scala.collection.immutable.Set[String] = Set(2hola, 44hola, 93hola)
Is it possible to implement the same functionality in Haskell's type system? If yes, how? A Haskell translation of the examples in above code snippet would be much appreciated. :-)
I don't think your first example is very Haskell-y, as you're overloading the same name to do two very different things. In Haskell, when you map a function over some container, you expect to get the same container type back. In fact, this is so common in Haskell that there is a type class, Functor which encapsulates this pattern.
All forms of overloading in Haskell boil down to using type classes, and while you could use those to achieve something similar, it would be very contrived and not very useful over just using plain functions that do just the one thing you want.
Prelude> import qualified Data.Map as M
Prelude Data.Map> let m = M.fromList [(2, 'a'), (6, 'b')]
Prelude Data.Map> M.map show $ M.mapKeys (+1) m
fromList [(3,"'a'"),(7,"'b'")]
Prelude Data.Map> M.keys m
[2,6]
I think your second example is more relevant to Haskell, as it's more about picking the most efficient implementation of a data structure based on the contained type, and I suspect this shouldn't be too difficult to do using type families, but I'm not too familiar with those, so I'll let someone else try to answer that part.
I very much agree with hammar, but here's a way to do it, sort of:
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, FlexibleInstances #-}
import Prelude hiding (map)
import qualified Data.Map as M
import qualified Data.IntSet as I
import qualified Data.Set as S
type family Elem c :: *
type instance Elem (M.Map k v) = (k, v)
type instance Elem I.IntSet = Int
type instance Elem (S.Set a) = a
class Map c o where
type Result c o :: *
map :: (Elem c -> o) -> c -> Result c o
instance Map I.IntSet Int where
type Result I.IntSet Int = I.IntSet
map = I.map
instance Map I.IntSet String where
type Result I.IntSet String = S.Set String
map f = S.fromList . fmap f . I.toList
instance (Ord k, Ord k1) => Map (M.Map k v) (k1, v1) where
type Result (M.Map k v) (k1, v1) = M.Map k1 v1
map f = M.fromList . fmap f . M.toList
instance (Ord k) => Map (M.Map k v) Int where
type Result (M.Map k v) Int = [Int]
map f = fmap f . M.toList
Here it is in action:
*Main> map fst (M.fromList [(2::Int, 'a'), (6, 'b')])
[2,6]
*Main> map (\(k, v) -> (k + 1, show v)) (M.fromList [(2, 'a'), (6, 'b')])
fromList [(3,"'a'"),(7,"'b'")]
*Main> :t it
it :: M.Map Integer [Char]
Ideally you'd want to do this:
instance (Ord k) => Map (M.Map k v) a where
type Result (M.Map k v) a = [a]
map f = fmap f . M.toList
But that instance conflicts with the one for pairs. So there's no good way to give an instance for every other type.
Adding to hammar: I think the second example is not possible as it stands, because there are implicit type conversions.
Ignoring that for the sake of the discussion, how could the type signature look like:
setmap :: (Set a, Set b) => a e -> (e -> f) -> b f
So, yes, this is conceivable, yet with the provision that one may need to specify the return type.