| CARVIEW |
pure-noise: High-performance composable noise generation (Perlin, Simplex, Cellular)
A high-performance noise generation library ported from FastNoiseLite. Provides N-dimensional noise functions (Perlin, OpenSimplex, SuperSimplex, Value, Cellular) that can be composed using Num or Fractional methods with minimal performance overhead. Noise values are generally clamped to [-1, 1]. Benefits significantly from LLVM backend compilation (~50-80% performance improvement).
[Skip to Readme]
Modules
[Index] [Quick Jump]
Downloads
- pure-noise-0.2.1.1.tar.gz [browse] (Cabal source package)
- Package description (as included in the package)
Maintainer's Corner
For package maintainers and hackage trustees
Candidates
- No Candidates
| Versions [RSS] | 0.1.0.0, 0.1.0.1, 0.2.0.0, 0.2.1.0, 0.2.1.1 |
|---|---|
| Change log | CHANGELOG.md |
| Dependencies | base (>=4.16 && <5), primitive (>=0.8 && <0.10) [details] |
| Tested with | ghc ==9.6.7, ghc ==9.8.4, ghc ==9.10.2 |
| License | BSD-3-Clause |
| Copyright | 2024 Jeremy Nuttall |
| Author | Jeremy Nuttall |
| Maintainer | jeremy@jeremy-nuttall.com |
| Uploaded | by jtnuttall at 2025-10-31T14:12:34Z |
| Category | Math, Numeric, Noise |
| Home page | https://github.com/jtnuttall/pure-noise#readme |
| Bug tracker | https://github.com/jtnuttall/pure-noise/issues |
| Source repo | head: git clone https://github.com/jtnuttall/pure-noise |
| Distributions | NixOS:0.2.1.1 |
| Downloads | 114 total (19 in the last 30 days) |
| Rating | (no votes yet) [estimated by Bayesian average] |
| Your Rating |
|
| Status | Docs uploaded by user Build status unknown [no reports yet] |
Readme for pure-noise-0.2.1.1
[back to package description]pure-noise
Performant, modern noise generation for Haskell with a minimal dependency footprint.
Core features
- algebraic composition of noise functions. You can combine,
layer, and transform noise sources using standard operators (E.g.,
Num,Fractional,Monad, etc). - Complex effects like domain warping and multi-octave fractals with clean, type-safe composition.
- 84-95% of C++ FastNoiseLite performance through aggressive optimization and LLVM compilation.
For detailed FastNoiseLite comparison, methodology, and reproducibility instructions, see the benchmark README.
The public interface for this library is unlikely to change much, although the
implementations (noiseBaseN functions and anything in Numeric.Noise.Internal)
are subject to change and may change between minor versions.
Acknowledgments
- This project grew from a port of the excellent FastNoiseLite library. The library structure has been tuned to perform well in Haskell and fit well with Haskell semantics, but the core noise implementations are the same.
- All credit for the original design, algorithms, and implementation goes to its creator Jordan Peck (@Auburn). I'm grateful for their work and the opportunity to learn from it.
- The original FastNoiseLite code, from which the core algorithms in this library were originally ported, is (C) 2020 Jordan Peck and is licensed under the MIT license, a copy of which is included in this repository.
Usage
The library provides composable noise functions. Noise2 and Noise3 are type
aliases for 2D and 3D noise. Noise functions can be composed transparently using
standard operators with minimal performance cost.
Noise values are generally clamped to [-1, 1], although some noise functions
may occasionally produce values slightly outside this range.
Basic Example
import Numeric.Noise qualified as Noise
-- Compose multiple noise sources
myNoise2 :: (RealFrac a) => Noise.Seed -> a -> a -> a
myNoise2 =
let fractalConfig = Noise.defaultFractalConfig
combined = (Noise.perlin2 + Noise.superSimplex2) / 2
in Noise.noise2At $ Noise.fractal2 fractalConfig combined
Advanced Features
The library's unified Noise p v type enables powerful composition patterns:
Complex Compositions
The Monad instance is useful to create noise that depends on other noise values:
-- Use one noise function's output to modulate another
complexNoise :: Noise.Noise2 Float
complexNoise = do
baseNoise <- Noise.perlin2
detailNoise <- Noise.next2 Noise.superSimplex2
-- Blend based on base noise: smooth areas get less detail
pure $ baseNoise * 0.7 + detailNoise * (0.3 * (1 + baseNoise) / 2)
This is especially useful for creating organic, varied terrain where one noise pattern influences the characteristics of another.
1D Noise via Slicing
Generate 1D noise by slicing higher-dimensional noise at a fixed coordinate:
-- Create 1D noise by fixing one dimension
noise1d :: Noise.Noise1 Float
noise1d = Noise.sliceY2 0.0 Noise.perlin2
-- Evaluate at a point
value = Noise.noise1At noise1d seed 5.0
Coordinate Transformation:
Scale, rotate, or warp the coordinate space:
-- Double the frequency
scaled = Noise.warp (\(x, y) -> (x * 2, y * 2)) Noise.perlin2
-- Rotate 45 degrees
rotated = Noise.warp (\(x, y) ->
let a = pi / 4
in (x * cos a - y * sin a, x * sin a + y * cos a)) Noise.perlin2
Layering Independent Noise
Use reseed or next2/next3 to create independent layers:
layered = (Noise.perlin2 + Noise.next2 Noise.perlin2) / 2
More examples can be found in bench and demo.
Domain Warping
Domain warping uses one noise function to distort the coordinate space of another, creating organic, flowing patterns ideal for terrain, clouds, and natural textures:
domainWarped :: Noise.Noise2 Float
domainWarped = do
-- Generate 3D fractal for warp offsets
let warpNoise = Noise.fractal3 Noise.defaultFractalConfig{Noise.octaves = 5} Noise.perlin3
-- Sample 3D noise at different slices to create warp offsets
warpX <- Noise.sliceX3 0.0 warpNoise -- Samples at (0, x, y)
warpY <- Noise.sliceY3 0.0 warpNoise -- Samples at (x, 0, y)
-- Apply warping to base noise coordinates
Noise.warp (\(x, y) -> (x + 30 * warpX, y + 30 * warpY))
$ Noise.fractal2 Noise.defaultFractalConfig{Noise.octaves = 5} Noise.openSimplex2

See the demo app for an interactive version with adjustable parameters.
Performance notes
- In single-threaded scenarios with LLVM enabled, this library achieves 84-95% of C++ FastNoiseLite performance.
- This library benefits considerably from compilation with the LLVM backend
(
-fllvm). Benchmarks suggest a ~50-80% difference depending on the kind of noise.
Parallel noise generation
This library integrates well with massiv for parallel computation. Parallel performance can reach 10-15x single-threaded performance.
This is the recommended approach for generating large noise textures or datasets.
Benchmarks
Results
Measured by values / second generated by the noise functions. These results come
from a benchmark with -fllvm enabled.
There's inevitably some noise in the measurements because all of the results are forced into an unboxed vector.
2D
| name | Float (values/sec) | Double (values/sec) |
|---|---|---|
| value2 | 173_511_654 | 189_119_731 |
| perlin2 | 154_674_464 | 161_114_532 |
| openSimplex2 | 74_747_031 | 74_332_345 |
| valueCubic2 | 61_415_544 | 62_481_313 |
| superSimplex2 | 51_295_369 | 50_383_577 |
| cellular2 | 34_996_382 | 32_652_899 |
3D
| name | Float (values/sec) | Double (values/sec) |
|---|---|---|
| value3 | 90_805_572 | 93_188_363 |
| perlin3 | 74_080_032 | 82_477_882 |
| valueCubic3 | 18_765_912 | 18_284_749 |
Examples
There's an interactive demo app in the demo directory.
OpenSimplex2

Perlin

Cellular
