Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell instance signatures

Tags:

haskell

I'm a complete newbie in Haskell so please be patient.

Let's say I've got this class

class Indexable i where
  at :: i a p -> p -> a

Now let's say I want to implement that typeclass for this data type:

data Test a p = Test [a]

What I tried is:

instance Indexable Test where
    at (Test l) p = l `genericIndex` p

However it didn't compile, because p needs to be an Integral, however as far as I understand, it's impossibile to add the type signature to instances. I tried to use InstanceSigs, but failed.

Any ideas?

like image 241
HaskellNewbie Avatar asked Jun 07 '26 01:06

HaskellNewbie


2 Answers

here is a version where you add the index-type to the class using MultiParamTypeClasses

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}

module Index where

import Data.List (genericIndex)

class Indexable i f  where
  at :: forall a . f a -> i -> a

data Test a = Test [a]

instance Integral i => Indexable i Test where
  at (Test as) i = as `genericIndex` i

here I need the FlexibleInstances because of the way the instance is declared and RankNTypes for the forall a . ;)

assuming this is your expected behavior:

λ> let test = Test [1..5]
λ> test `at` 3
4
λ> test `at` 0
1
λ> test `at` (0 :: Int)
1
λ> test `at` (1 :: Integer)
2
like image 106
Random Dev Avatar answered Jun 09 '26 14:06

Random Dev


Just for fun, here's a very different solution which doesn't require any changes to your class declaration. (N.B. This answer is for fun only! I do not advocate keeping your class as-is; it seems a strange class definition to me.) The idea here is to push the burden of proof off from the class instance to the person constructing a value of type Test p a; we will demand that constructing such a value will require an Integral p instance in scope.

All this code stays exactly the same (but with a new extension turned on):

{-# LANGUAGE GADTs #-}
import Data.List

class Indexable i where
    at :: i a p -> p -> a
instance Indexable Test where
    at (Test l) p = l `genericIndex` p

But the declaration of your data type changes just slightly to demand an Integral p instance:

data Test a p where
    Test :: Integral p => [a] -> Test a p
like image 25
Daniel Wagner Avatar answered Jun 09 '26 14:06

Daniel Wagner