Other data structures
Beyond lists and tuples, SCL provides several specialized data structures for different
performance and mutability requirements.
Vector
Vector is a dense array backed by a Java array. It is more efficient than [a] (linked
list) for numeric data and random access by index:
import "Vector"
v :: Vector Double
v = vector [1.0, 2.0, 3.0, 4.0, 5.0]
> v ! 2
3.0
> length v
5
Vector a and [a] are interconvertible:
vector :: [a] -> Vector a
vectorToList :: Vector a -> [a]
Use Vector when:
- You need O(1) indexed access by position.
- The data is numeric and will be accessed many times.
- You are interfacing with Java APIs that expect arrays.
Map
Map.T k v is a functional (immutable) hash map from keys of type k to values of type
v. Import the module qualified to avoid name clashes:
import "Map" as Map
m :: Map.T String Integer
m = Map.fromList [("a", 1), ("b", 2), ("c", 3)]
> Map.get m "b"
Just 2
> Map.get m "z"
Nothing
Key operations:
Map.empty :: Map.T k v
Map.singleton :: k -> v -> Map.T k v
Map.fromList :: [(k,v)] -> Map.T k v
Map.toList :: Map.T k v -> [(k,v)]
Map.get :: Map.T k v -> k -> Maybe v
Map.put :: Map.T k v -> k -> v -> Map.T k v
Map.remove :: Map.T k v -> k -> Map.T k v
Map.size :: Map.T k v -> Integer
Map.keys :: Map.T k v -> [k]
Map.values :: Map.T k v -> [v]
Set
Set.T a is a functional (immutable) hash set of elements of type a:
import "Set" as Set
s :: Set.T String
s = Set.fromList ["apple", "banana", "cherry"]
> Set.member s "banana"
True
> Set.member s "grape"
False
Key operations:
Set.empty :: Set.T a
Set.fromList :: [a] -> Set.T a
Set.toList :: Set.T a -> [a]
Set.member :: Set.T a -> a -> Boolean
Set.add :: Set.T a -> a -> Set.T a
Set.remove :: Set.T a -> a -> Set.T a
Set.size :: Set.T a -> Integer
Set.union :: Set.T a -> Set.T a -> Set.T a
Set.intersect :: Set.T a -> Set.T a -> Set.T a
Mutable data structures
For algorithms that naturally require mutation, SCL provides mutable companions to the
immutable types.
MList (mutable list)
import "MList"
buildList :: <Proc> [Integer]
buildList = do
ml = MList.create ()
for [1..10] $ \i ->
MList.add ml (i * i)
MList.freeze ml // converts to immutable [Integer]
MMap (mutable map)
import "MMap"
countWords :: [String] -> <Proc> Map.T String Integer
countWords words = do
mm = MMap.create ()
for words $ \w -> do
current = fromMaybe 0 (MMap.get mm w)
MMap.put mm w (current + 1)
MMap.freeze mm
MSet (mutable set)
import "MSet"
uniqueItems :: [String] -> <Proc> Set.T String
uniqueItems items = do
ms = MSet.create ()
for items $ \item ->
MSet.add ms item
MSet.freeze ms
freeze converts the mutable structure to its corresponding immutable type. After
freezing, the mutable structure should no longer be used.
Ref — mutable references
Ref a is a single mutable cell holding a value of type a. See 1.08 Side effects
for details.
import "Prelude"
counter :: <Proc> Integer
counter = do
c = ref 0
for [1..10] $ \_ ->
c := getRef c + 1
getRef c
Coercion
The Coercion module provides type-safe coercions between compatible types:
import "Coercion"
coerce :: a -> b // only valid when a and b are coercible
Built-in coercions cover numeric conversions, String/[Character], and newtype
wrappers. User-defined coercions can be added via type class instances. Use coerce only
when you are certain the types are representationally compatible; misuse causes runtime
errors.
|