Skip to content

Commit 0b49a62

Browse files
Add HeterogenousArrayLog (#173)
* Add HeterogenousArrayLog * Regenerate readme * Add additional comments clarifying some things * Port comment explaining why Variant needs to be used to recipe Readme * Reword description to note exceptional nature of this approach * Add sum type version to compare with Variant version * Cleanup comment readability * purty formatting * Simplify examples Co-authored-by: Miles Frain <[email protected]>
1 parent 22ee469 commit 0b49a62

File tree

8 files changed

+169
-0
lines changed

8 files changed

+169
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ Running a web-compatible recipe:
108108
| | :heavy_check_mark: | [HelloHalogenHooks](recipes/HelloHalogenHooks) | A Halogen port of the ["HTML - Hello" Elm Example](https://elm-lang.org/examples/hello). |
109109
| | :heavy_check_mark: | [HelloReactHooks](recipes/HelloReactHooks) | A React port of the ["HTML - Hello" Elm Example](https://elm-lang.org/examples/hello). |
110110
| :heavy_check_mark: | :heavy_check_mark: | [HelloWorldLog](recipes/HelloWorldLog) | This recipe shows how to run a simple "Hello world!" program in either the node.js or web browser console. |
111+
| :heavy_check_mark: | :heavy_check_mark: | [HeterogenousArrayLog](recipes/HeterogenousArrayLog) | This recipe demonstrates how to create a heterogenous array and process its elements. |
111112
| | :heavy_check_mark: | [ImagePreviewsHalogenHooks](recipes/ImagePreviewsHalogenHooks) | A Halogen port of the ["Files - Drag-and-Drop" Elm Example](https://elm-lang.org/examples/drag-and-drop). |
112113
| | :heavy_check_mark: | [NumbersHalogenHooks](recipes/NumbersHalogenHooks) | A Halogen port of the ["Random - Numbers" Elm Example](https://elm-lang.org/examples/numbers). |
113114
| | :heavy_check_mark: | [NumbersReactHooks](recipes/NumbersReactHooks) | A React port of the ["Random - Numbers" Elm Example](https://elm-lang.org/examples/numbers). |
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/bower_components/
2+
/node_modules/
3+
/.pulp-cache/
4+
/output/
5+
/generated-docs/
6+
/.psc-package/
7+
/.psc*
8+
/.purs*
9+
/.psa*
10+
/.spago
11+
/web-dist/
12+
/prod-dist/
13+
/prod/
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# HeterogenousArrayLog
2+
3+
This recipe demonstrates how to create a heterogenous array and process its elements.
4+
5+
PureScript arrays are _homogeneous_, meaning that all values must have the same type. If you want to store values with different types in the same array (i.e. a _heterogeneous_ array), you should wrap all the types you wish to store in either a [sum type](https://github.com/purescript/documentation/blob/master/language/Types.md#tagged-unions) or a [Variant](https://pursuit.purescript.org/packages/purescript-variant). This recipe demonstrates both strategies.
6+
7+
## Expected Behavior:
8+
9+
Prints the following:
10+
```
11+
---- Using Sum Type ----
12+
["a String value","4","true","false","82.4"]
13+
14+
---- Using Variant Type ----
15+
["a String value","4","true","false","82.4"]
16+
```
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This file just indicates that the node backend is supported.
2+
It is used for CI and autogeneration purposes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{ name = "HeterogenousArrayLog"
2+
, dependencies =
3+
[ "console", "effect", "psci-support", "variant", "arrays" ]
4+
, packages = ../../packages.dhall
5+
, sources = [ "recipes/HeterogenousArrayLog/src/**/*.purs" ]
6+
}
7+
{-
8+
sources does not work with paths relative to this config
9+
sources = [ "src/**/*.purs" ]
10+
Paths must be relative to where this command is run
11+
-}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
module HeterogenousArrayLog.Main where
2+
3+
import Prelude
4+
import Data.Functor.Variant (SProxy(..))
5+
import Data.Variant (Variant)
6+
import Data.Variant as Variant
7+
import Effect (Effect)
8+
import Effect.Class.Console (logShow)
9+
import Effect.Console (log)
10+
11+
main :: Effect Unit
12+
main = do
13+
log "---- Using Sum Type ----"
14+
heterogenousArrayViaSumType
15+
log "\n---- Using Variant Type ----"
16+
heterogenousArrayViaVariant
17+
18+
-------------- Sum Type Example --------------
19+
--
20+
-- Sum Type for array elements
21+
data SumType
22+
= Str String
23+
| Integer Int
24+
| Bool Boolean
25+
| Num Number
26+
27+
heterogenousArrayViaSumType :: Effect Unit
28+
heterogenousArrayViaSumType = do
29+
let
30+
-- Create array
31+
heterogenousArray :: Array SumType
32+
heterogenousArray =
33+
[ Str "a String value"
34+
, Integer 4
35+
, Bool true
36+
, Bool false
37+
, Num 82.4
38+
]
39+
40+
-- Demonstrate how to process array elements with a function
41+
-- that converts values of our SumType to strings for logging.
42+
-- Note, you could create a Show instance for SumType instead.
43+
showElement :: SumType -> String
44+
showElement = case _ of
45+
Str s -> s
46+
Integer i -> show i
47+
Bool b -> show b
48+
Num n -> show n
49+
--
50+
-- Show array
51+
logShow $ map showElement heterogenousArray
52+
53+
-------------- Variant Type Example --------------
54+
--
55+
-- Variant Type for array elements
56+
-- Created from a "row type" of tags and other types
57+
type VariantType
58+
= Variant
59+
( typeLevelString :: String
60+
, int :: Int
61+
, boolean :: Boolean
62+
, "this type level string must match the label of the row" :: Number
63+
)
64+
65+
heterogenousArrayViaVariant :: Effect Unit
66+
heterogenousArrayViaVariant = do
67+
let
68+
-- Setup some SProxy values with types matching those found within our VariantType
69+
--
70+
-- Read: "This particular `SProxy` value has the type
71+
-- `SProxy "typeLevelString"`..."
72+
_typeLevelString :: SProxy "typeLevelString"
73+
_typeLevelString = SProxy
74+
75+
-- ... which differs from `SProxy "int"` and the other SProxy types below.
76+
-- Note that we can write these on one line as:
77+
_intValue = (SProxy :: SProxy "int")
78+
79+
-- This shorthand style is also allowed:
80+
_boolean = (SProxy :: _ "boolean")
81+
82+
-- Any string may be used as a type-level label
83+
_arbitraryTypeLevelString = (SProxy :: _ "this type level string must match the label of the row")
84+
85+
-- Create array
86+
heterogenousArray :: Array VariantType
87+
heterogenousArray =
88+
-- To create a value of type `Variant`, we must inject a value into
89+
-- the data type using a type-level string that refers to the
90+
-- corresponding row (i.e. a label-type association)
91+
[ Variant.inj _typeLevelString "a String value"
92+
, Variant.inj _intValue 4
93+
, Variant.inj _boolean true
94+
-- You may also skip creating the SProxy helper values, and just write them inline:
95+
, Variant.inj (SProxy :: _ "boolean") false
96+
, Variant.inj _arbitraryTypeLevelString 82.4
97+
]
98+
99+
-- Demonstrate how to process array elements with a function
100+
-- that converts values of our VariantType to strings for logging.
101+
-- Note, you could create a Show instance for VariantType instead.
102+
showElement :: VariantType -> String
103+
showElement =
104+
Variant.case_
105+
# Variant.on _typeLevelString identity
106+
# Variant.on (SProxy :: _ "int") show -- inline example
107+
# Variant.on _boolean show
108+
# Variant.on _arbitraryTypeLevelString show
109+
--
110+
-- Show array
111+
logShow $ map showElement heterogenousArray
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<title>HeterogenousArrayLog</title>
7+
</head>
8+
9+
<body>
10+
<script src="./index.js"></script>
11+
</body>
12+
13+
</html>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"use strict";
2+
require("../../../output/HeterogenousArrayLog.Main/index.js").main();

0 commit comments

Comments
 (0)