[Haskell-cafe] can't figure out a type
John Lato
jwlato at gmail.com
Thu Feb 12 18:22:03 EST 2009
One clarification. That is, I could write map with the cNull/cCons
implementation already suggested, but I couldn't do:
instance Chunkable Data.StorableVector.Vector el where
...
cMap = Data.StorableVector.map
which is what I really want.
However, I just realized that I should be able to use the cNull cCons
implementation with a rewrite rule for this case, so I think I'm happy
now.
John
On Thu, Feb 12, 2009 at 11:08 PM, John Lato <jwlato at gmail.com> wrote:
> Hi Job, thanks for replying.
>
> Thanks for explaining this. I never really thought about the
> implications of kinds on type classes, and it's all much more clear
> now.
>
> The first version, with only one parameter, almost works, except that
> some instances (e.g. uvector, storablevector) have further class
> restrictions on the element types. I believe these are impossible to
> express without the element parameter included in the Chunkable class.
> This was a big disappointment, because otherwise it would be
> possible in Haskell98.
>
> This is also a problem with the map implementation. Since the
> typeclass restriction exists for both el and el', I don't see how it's
> possible to type cMap without including el' in the class. I don't
> want to do that, so I guess the map function will just need to be
> provided outside the class instance. It does turn out that I don't
> need either fundeps or type families at least.
>
> Thanks to everyone who replied; it really helped me clarify my
> thoughts on this implementation.
>
> Cheers,
> John Lato
>
> On Wed, Feb 11, 2009 at 8:28 PM, Job Vranish <jvranish at gmail.com> wrote:
>> I think what you probably want is something like this:
>>
>> class Chunckable c where
>> cLength :: c el -> Int
>> cHead :: c el -> Maybe el
>> cMap :: (a -> b) -> c a -> c b
>>
>> instance Chunckable [] where
>> cLength [] = 0
>> cLength (x:xs) = 1 + cLength xs
>>
>> cHead [] = Nothing
>> cHead (x:xs) = Just x
>>
>> cMap = map
>>
>> a = [4, 7, 3, 8]
>> test1 = cLength a
>> test2 = cHead a
>> test3 = cMap (Just) a
>>
>>
>> The class does not actually need the second type parameter.
>> You can actually use all sorts of extra type variables in the type
>> signatures in class declarations as long as all your instances are
>> polymorphic across those types (not sure if that's the precise
>> terminology). Basically, as long as cLength, cHead and cMap do the
>> same thing regardless of what el is, then you don't need to have el as
>> a type parameter to the class.
>>
>> Now if you _do_ want to have cLength, etc do something else depending
>> el, then things get more complicated. Maybe something like this:
>>
>> class Chunckable2 c el where
>> cLength2 :: c el -> Int
>> cHead2 :: c el -> Maybe el
>> cMap2 :: (Chunckable2 c el') => (el -> el') -> c el -> c el'
>>
>> instance Chunckable2 [] Int where
>> cLength2 [] = 0
>> cLength2 (x:xs) = 1 + cLength xs
>>
>> cHead2 [] = Nothing
>> cHead2 (x:xs) = Just x
>>
>> cMap2 = map
>>
>> instance Chunckable2 [] Float where
>> cLength2 [] = 0
>> cLength2 (x:xs) = 1 + cLength xs
>>
>> cHead2 [] = Nothing
>> cHead2 (x:xs) = Just x
>>
>> cMap2 f xs = []
>>
>> test4 = cMap2 (fromIntegral) (a::[Int]) :: [Float]
>> test5 = cMap2 (id) ([3.0, 4.0, 1.0]::[Float]) :: [Float]
>>
>> Note that if you want things to work like this, functional
>> dependencies wont help you out (as they don't make sense in this case)
>>
>>
>>
>> On Wed, Feb 11, 2009 at 12:34 PM, John Lato <jwlato at gmail.com> wrote:
>>> Hi Job,
>>>
>>> Thanks for answering. What I'm trying to do is probably very simple,
>>> and I think the biggest problem is that I don't fully understand kinds
>>> yet.
>>>
>>> Here's an example instance:
>>>
>>> instance Chunkable [a] a where
>>> cmap = map
>>> --etc.
>>>
>>> In the class I wrote, c has kind * (e.g. [a]), but then I don't see
>>> how to write a suitable map function. For that, I would want c to
>>> have kind * -> *. Unfortunately then I don't know to write the
>>> others.
>>>
>>> Would I have to do something with c having kind (* -> *) ?
>>>
>>> class Chunkable2 c el where
>>> cLength :: c el -> Int
>>> cHead :: c el -> Maybe el
>>> cMap :: (el -> el') -> c el -> c el'
>>>
>>> Sincerely,
>>> John
>>>
>>> On Wed, Feb 11, 2009 at 5:12 PM, Job Vranish <jvranish at gmail.com> wrote:
>>>> What do you mean by parameterized over a different type?
>>>> will c have a kind of * -> * ? I don't think it has to be for what you
>>>> want to work, but the idea of "same instance" will go out the window.
>>>>
>>>> Do you have a small usage example?
>>>>
>>>>
>>>> On Wed, Feb 11, 2009 at 11:52 AM, John Lato <jwlato at gmail.com> wrote:
>>>>> Hello,
>>>>>
>>>>> I'm working on some code like the following:
>>>>>
>>>>>> class Chunkable c el | c -> el where
>>>>>> cLength :: c -> Int
>>>>>> cHead :: c -> Maybe el
>>>>>
>>>>> I want to be able to map over this type, like this:
>>>>>
>>>>>> cMap :: Chunkable c' el' => (el -> el') -> c -> c'
>>>>>
>>>>> but this isn't quite right. c' shouldn't be any instance of
>>>>> Chunkable, it should be the same instance except parameterized over a
>>>>> different type. Another approach would be something like:
>>>>>
>>>>> class (Functor c) => Chunkable c el
>>>>> ...
>>>>>
>>>>> except that's not right either. I think c has the wrong kind to be a
>>>>> Functor instance.
>>>>>
>>>>> I expect there's something very basic I'm missing. Could anyone point
>>>>> in the proper direction of how to do this? Can this be expressed with
>>>>> associated types, perhaps?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> John Lato
>>>>> _______________________________________________
>>>>> Haskell-Cafe mailing list
>>>>> Haskell-Cafe at haskell.org
>>>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>>>
>>>>
>>>
>>
>
More information about the Haskell-Cafe
mailing list