Skip to content

Add transpose to NonEmptyArray #227

Closed
@newlandsvalley

Description

@newlandsvalley

I've had a look at modifying both implementations we have for the normal Array case detailed in #225 for use with a NonEmptyArray. I came up with this one based on my implementation:

import Data.Array.NonEmpty
import Data.Array.NonEmpty.Internal (NonEmptyArray(..))
import Data.Maybe (Maybe(..))
import Prelude (map)

transpose :: forall a. NonEmptyArray (NonEmptyArray a) -> NonEmptyArray (NonEmptyArray a)
transpose x = 
  case (mapMaybe tail' x) of 
    [] -> 
      singleton (map head x)
    end -> 
      cons (map head x) (transpose (unsafeFromArray end))

  where
  tail' :: NonEmptyArray a -> Maybe (NonEmptyArray a)
  tail' x = 
    case tail x of 
      [] -> Nothing 
      end -> Just (unsafeFromArray end)

unsafeFromArray :: forall a. Array a -> NonEmptyArray a
unsafeFromArray = NonEmptyArray

and this one based on the implementation from @JordanMartinez :

import Prelude
import Data.Array as A
import Data.Array.NonEmpty
import Data.Array.NonEmpty.Internal (NonEmptyArray(..))
import Data.Maybe (Maybe(..), maybe)
import Data.Foldable (foldl) 

transpose :: forall a. NonEmptyArray (NonEmptyArray a) -> NonEmptyArray (NonEmptyArray a)
transpose xs = unsafeFromArray $ go 0 []
  where
  go :: Int -> Array (NonEmptyArray a) -> Array (NonEmptyArray a)
  go idx allArrays = case buildNext idx of
    Nothing -> allArrays
    Just next -> go (idx + 1) (A.snoc allArrays next)
    
  buildNext :: Int -> Maybe (NonEmptyArray a)
  buildNext idx = 
    xs # flip foldl Nothing \acc nextArr -> do
      maybe acc (\el -> Just $ maybe (singleton el) (flip snoc el) acc) $ index nextArr idx

unsafeFromArray :: forall a. Array a -> NonEmptyArray a
unsafeFromArray = NonEmptyArray

All the tests pass for whichever version, but performance comparisons show the same pattern as for Array - Jordan's is again about three times faster than mine and is only a little slower than for Array. I'm slightly concerned about the use of unsafeFromArray at the top level, but I think it's legitimate and many other functions in the module rely on it.

If you're agreeable, I'll raise a PR using this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions