Haskell proporciona en Data.Array.IArray un tipo Array de matrices inmutables. Esto permite utilizar matrices dentro del código funcional. ¿Es posible hacer coincidir Array s con patrones, de la misma manera que es posible para las listas?

Me gustaría que el siguiente código funcione ...

function :: Ix a => Array a b -> ...

function [| x |]         = ... -- matches if arg has one element
function [| x, y |]      = ... -- matches if arg has two elements
function [| x, ..., y |] = ... -- matches if arg has more than 3 elements and
                               -- binds the first and last element with x and y

Nota: esta función existe en el idioma de Rust; consulte https: //doc.rust- lang.org/book/slice-patterns.html

4
user19018 31 jul. 2016 a las 23:14

2 respuestas

La mejor respuesta

Voy a responder esto para Data.Vector o Data.Vector.Unboxed porque no creo que la pregunta tenga sentido en términos de Data.Array.IArray multidimensional ...

Puede hacer algo como ViewL y ViewR en Data.Sequence. Adaptando eso, podrías tener

data ViewL a
    = EmptyL        -- ^ empty vector
    | a :< Vector a -- ^ leftmost element and the rest of the vector

data ViewR a
    = EmptyR        -- ^ empty vector
    | Vector a :> a -- ^ rest of the vector and the rightmost element

Entonces, podrías definir funciones

viewl :: Vector a -> ViewL a
viewl v | null v = EmptyL
        | otherwise = head v :< tail v 

viewr :: Vector a -> ViewR a
viewr v | null v = EmptyR
        | otherwise = init v :> last v 

viewlr :: Vector a -> (ViewL a, ViewR a)
viewlr v = (viewl v, viewr v) -- or `viewl &&& viewr` if you like Control.Arrows

Y utilícelos con ViewPatterns extensión:

function :: Vector a -> ...
function (viewl -> x :< EmptyL)      = ... -- matches if arg has one element
function (viewl -> x :< y:< EmptyL)  = ... -- matches if arg has two elements
function (viewlr -> (x :< _, _ :> y) = ... -- matches `x` and `y` to the first and
                                           -- last elements
function (viewlr -> (x :< _ :< _ :< _, _ :> y) = ... -- matches if arg has more
                                                     -- than 3 elements and binds 
                                                     -- the first and last element
                                                     -- with x and y

Dado que tail y init son cortes de O (1) para Data.Vector, esto considera perezosamente sólo tantos elementos del vector como sea necesario.

1
Alec 1 ago. 2016 a las 22:47

Primero, tenga en cuenta que las matrices de Haskell pueden ser multidimensionales.

Podrías escribir tu función de ejemplo así:

import Data.Array.IArray
import Data.Ix

foo arr
  | first == last = print x      -- single element case
  | otherwise     = print (x,y)  -- more than one element case
  where (first,last) = bounds arr
        x = arr ! first
        y = arr ! last
2
ErikR 31 jul. 2016 a las 20:40