Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typeclasses to Unify Collection Types #33

Open
BebeSparkelSparkel opened this issue Dec 31, 2018 · 6 comments
Open

Typeclasses to Unify Collection Types #33

BebeSparkelSparkel opened this issue Dec 31, 2018 · 6 comments
Assignees

Comments

@BebeSparkelSparkel
Copy link

I've been working with multiple collection types like List, Sequence, Dequeue, Vector, and NonEmpty. It has been a frustrating process to switch between the different collection types, so I have been building typeclasses to unify the functions that they share in common. This way I can write functions that specify constraints of the type instead of specifying the actual collection type.

I would like to present what I have implemented and receive feedback on how to improve my implementation.

30min

@filippovitale
Copy link
Contributor

Which language are you using for the implementation?

@mwotton
Copy link
Contributor

mwotton commented Dec 31, 2018 via email

@BebeSparkelSparkel
Copy link
Author

@mwotton I was talking with @jjant about this and he was suggesting Lenses as well, and I am researching them this week. It seems that I have unknowingly been writing lenses for the different containers that I have been using.
The more I learn about lenses the less sense the existence the container specific functions make. They seem to be the legacy of when lenses didn't exist. Examples: : for [] and <| for Seq

Do you know if those functions will be dropped in the future for the lens functions?

Also, it seems like lenses are ripe to become a language extension for things like pattern matching but I have not found such extension in the GHC Language Features

Here are some of the typeclasses that I have been making

class Length t where
  length :: t a -> Int

  lengthEq :: t a -> Int -> Bool
  lengthEq xs l = (== l) $ length xs

  lengthGT :: t a -> Int -> Bool
  lengthGT xs l = (> l) $ length xs

  lengthGTEq :: t a -> Int -> Bool
  lengthGTEq xs l = lengthGT xs $ l - 1

class Init t where
  init :: t a -> Maybe (t a)

class Tail t where
  tail :: t a -> Maybe (t a)

  drop :: Int -> t a -> Maybe (t a)
  drop 0 xs = Just xs
  drop i (tail -> Just xs) = drop (i - 1) xs
  drop _ _ = Nothing

infixr 5 <|
class Cons t where
  (<|) :: a -> t a -> t a
  (|>) :: t a -> a -> t a

class Singleton t where
  singleton :: a -> t a

class Index t where
  (!!) :: Int -> t a -> Maybe a

class Reverse t where
  reverse :: t -> t

class DeleteAt t where
  deleteAt :: Int -> t a -> Maybe (t a)

class Sort t where
  sort :: Ord a => t a -> t a
  sort = sortOn id

  sortOn :: Ord b => (a -> b) -> t a -> t a

class SplitAt t where
  splitAt :: Int -> t a -> Maybe (t a, t a)

class Zip t where
  zip :: t a -> t b -> t (a, b)
  zip = zipWith (,)

  zipWith :: (a -> b -> c) -> t a -> t b -> t c

  zip3 :: t a -> t b -> t c -> t (a, b, c)
  zip3 = zipWith3 (,,)

  zipWith3 :: (a -> b -> c -> d) -> t a -> t b -> t c -> t d
  zipWith3 f xs ys = zipWith ($) (zipWith f xs ys)

  zip4 :: t a -> t b -> t c -> t d -> t (a, b, c, d)
  zip4 = zipWith4 (,,,)

  zipWith4 :: (a -> b -> c -> d -> e) -> t a -> t b -> t c -> t d -> t e
  zipWith4 f xs ys zs = zipWith ($) (zipWith3 f xs ys zs)

class UnZip t where
  unzip :: t (a, b) -> (t a, t b)
  unzipWith :: (a -> (b, c)) -> t a -> (t b, t c)

instance (Functor t) => UnZip t where
  unzip = fmap fst &&& fmap snd
  unzipWith f = unzip . fmap f



-- Potentially Empty --

class Head t where
  head :: t a -> Maybe a

class Last t where
  last :: t a -> Maybe a

class Filter t where
  filter :: (a -> Bool) -> t a -> t a

class Take t where
  take :: Int -> t a -> t a
  takeWhile :: (a -> Bool) -> t a -> t a

class Empty t where
  empty :: t a

class IsEmpty t where
  isEmpty :: t a -> Bool

class FromNativeList t where
  fromNativeList :: [a] -> t a

class Replicate t where
  replicate :: Int -> a -> t a

-- NonEmpty --

class HeadNE t where
  headNE :: t a -> a
-- instance HeadNE t => Head t where head = Just . headNE

class LastNE t where
  lastNE :: t a -> a
-- instance LastNE t => Last t where last = Just . lastNE

class FilterNE t where
  filterNE :: (a -> Bool) -> t a -> Maybe (t a)

class TakeNE t where
  takeNE :: Int -> t a -> t a
  takeWhileLNE :: (a -> Bool) -> t a -> Maybe (t a)

@BebeSparkelSparkel
Copy link
Author

BebeSparkelSparkel commented Jan 2, 2019

@filippovitale Probably going to switch this over to a lens talk for haskell. I probably won't be ready this month, but I'll probably know enough next month to give the talk.

@mwotton
Copy link
Contributor

mwotton commented Jan 2, 2019

I wouldn't expect lenses to become part of haskell syntax proper - there's still a bit of ideological tug-of-war over it. definitely useful for this sort of thing though.

@BebeSparkelSparkel
Copy link
Author

After looking through lenses a bit it seems like haskell's type system is lacking expressiveness to adequately show what's going on. Is that a thing or am I just not familiar enough with lens?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants