4 ms·
greet :: forall r. { name :: String | r } -> String greet person = "Hello, " <> person.name <> "!" greetWithAge :: forall r. { name :: String, age :: Int |
by tmountain 2y ago
greet :: forall r. { name :: String | r } -> String
greet person = "Hello, " <> person.name <> "!"
greetWithAge :: forall r. { name :: String, age :: Int | r } -> String
greetWithAge person =
"Hello, " <> person.name <> "! You are " <> show person.age <> " years old."
main :: Effect Unit
main = do
let person = { name: "Alice", age: 30, occupation: "Engineer" }
-- greet can accept the person record even though it has more fields
log (greet person) -- Output: "Hello, Alice!"
-- greetWithAge can also accept the person record
log (greetWithAge person)
- blue_pants 2y agoHow does it differ from structural typing in TypeScript though?
- tmountain 2y agoStructural typing relies on interface compatibility. Row polymorphism is a type-level feature in PureScript where record types are constructed with an explicit "row" of fields. In Practice, row polymorphism is more granular, allowing you to explicitly allow certain fields while tracking all other fields via a ("rest") type variable. Example: PureScript allows you to remove specific fields from a record type. This feature, is called record subtraction, and it allows more flexibility when transforming or narrowing down records. You can also apply exact field constraints; meaning, you can constrain records to have exactly the fields you specify. Lastly, PureScript allows you to abstract over rows using higher-kinded types. You can create polymorphic functions that accept any record with a flexible set of fields and can transform or manipulate those fields in various ways. This level of abstraction is not possible in TypeScript. These are just a few examples. In the most general sense, you can think of row polymorphism as a really robust tool that gives you a ton of flexibility regarding strictness and validation.
- blue_pants 2y ago> PureScript allows you to remove specific fields from a record type. This feature, is called record subtraction, and it allows more flexibility when transforming or narrowing down records. TypeScript does allow you to remove specific fields, if I understand you right [0]: function removeField<T, K extends keyof T>(obj: T, field: K): Omit<T, K> { const { [field]: _, ...rest } = obj; return rest; } type Person = { name: string; age: number }; declare const p: Person; const result = removeField(p, 'age'); // result is of type: Omit<Person, "age"> > PureScript allows you to abstract over rows using higher-kinded types. You can create polymorphic functions that accept any record with a flexible set of fields and can transform or manipulate those fields in various ways. This level of abstraction is not possible in TypeScript. Again, if I understand you correctly, then TypeScript is able to do fancy manipulations of arbitrary records [1]: type StringToNumber<T> = { [K in keyof T]: T[K] extends string ? number : T[K] } function stringToLength<T extends Record<string, unknown>>(obj: T): StringToNumber<T> { const result: Record<string, unknown> = {}; for (const key in obj) { result[key] = typeof obj[key] === 'string' ? obj[key].length : obj[key]; } return result as StringToNumber<T>; } const data = { name: "Alice", age: 30, city: "New York" }; const lengths = stringToLength(data); lengths.name // number lengths.age // number lengths.city // number [0] https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABAJwKYFs4DdUDEaoA2AJgDwAqANIgNKKoAeUqYxAzogNaoCecwicgD4AFHABGAKwBcg6sAIlZNAJSyA8uhhQK1GkMQBvALAAoRBcQQEbKEcQBtBUWIBdWQH1qAOl9pbiAC+iAC8iBKSANxmliioUCDISP5Q0aaBZmZQPAAOqIgACqjIbAih9mAAhuiosrbIMGAA5pGIlU21iGAg6OLFQWlmxKgQhJVoVjZ2ObJFJQiDptZgAf4ghHZhaJg4+C4iOdQA5O2oRyqtAPSXiJrapHOlYNQARKcvQmbXsYgAegD8QA https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABA... [1] https://www.typescriptlang.org/play/?#code/C4TwDgpgBAysBOBLAdgcwCoHsByBXAtgEYTwA86AfFALxQDeAsAFBStQDaA0lClANYQQmAGZR0AXQBcYruKgQAHsAjIAJgGco6hClRQA-FGQFi8KNPSzmAX2bNhuZAGNgiTMi060WADIrUwAAW5PJKKhpQAEoQTpjwqqTaSGgANFCOfMiYAO7IFBQAFJiEAFYWAJTScMkYOCYk5FSMLGyxyNpQ8BDquAA2wNLRsfGJXqhpGVm5VLR01gDczGxQwnFQBW0dAiA8HsUl5fRLy2xdPf3s23K0oJAiUPuXgtfUtADkSbpvBg+lTyDiAB0vX8QXMvxK-3EixarFssM6EGAuHgHjOfWAUAAhppqrosHgiA1KDD4cxNpjVFjgFiaEcEcgsfgINIAEQAQV6iCcEFZKWOrCxqBZUAAzAAGfkIpyIUBs7AQbJQACacT4rJsMPJ7g6ILQQU0tE+3kwfn1gQKVJp5S1TD1AUC6kBjOZUAA9G6jPV4Mx7QbAULoB6vUSfXbQY7ATLQO7PcZQ0A https://www.typescriptlang.org/play/?#code/C4TwDgpgBAysBOBLA... edit: provided links to TS playground
- jy14898 2y ago
- tmoertel 2y agoCan `greetWithAge` be implemented using `greet`?
- runeks 2y agoThank you, but I was looking for real world examples solved by row types as OP implied there were plenty of.