https://github.com/fricklerhandwerk/haskell-record-access
Unqualified shower thoughts about Haskell
https://github.com/fricklerhandwerk/haskell-record-access
haskell learning
Last synced: 26 days ago
JSON representation
Unqualified shower thoughts about Haskell
- Host: GitHub
- URL: https://github.com/fricklerhandwerk/haskell-record-access
- Owner: fricklerhandwerk
- Created: 2024-08-27T18:04:33.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-08-27T18:12:01.000Z (over 1 year ago)
- Last Synced: 2025-01-22T08:37:29.491Z (about 1 year ago)
- Topics: haskell, learning
- Language: Nix
- Homepage:
- Size: 3.91 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Man discovers Haskell language extensions
I wondered if it's possible to access Haskell record fields with a dot notation.
Turns out it is.
My initial idea was to namespace the accessor functions by separating types out into modules and importing them qualified.
That actually worked elegantly:
```haskell
module Main where
import MyType (MyType(..))
main :: IO ()
main = do
let myValue = MyType { foo = 42 }
putStrLn $ "myValue = " ++ show (MyType.foo myValue)
```
However, one can't have another type that also has a field `foo`.
This can be alleviated with the [`DuplicateRecordFields`](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/duplicate_record_fields.html) language extension:
```haskell
{-# LANGUAGE DuplicateRecordFields #-}
module Main where
import MyType (MyType(..))
import AnotherType (AnotherType(..))
main :: IO ()
main = do
let myValue = MyType { foo = 42 }
let anotherValue = AnotherType { foo = "bar" }
putStrLn $ "myValue = " ++ show (MyType.foo myValue)
putStrLn $ "anotherValue = " ++ show (AnotherType.foo anotherValue)
```
One still can't use field names as variable names, although they're clearly distinct semantically.
This can be helped with [`NoFieldSelectors`](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/field_selectors.html):
```haskell
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE DuplicateRecordFields #-}
module Main where
import MyType (MyType(..))
import AnotherType (AnotherType(..))
main :: IO ()
main = do
let foo = MyType { foo = 42 }
let bar = AnotherType { foo = "bar" }
putStrLn $ "foo = " ++ show (MyType.foo foo)
putStrLn $ "bar = " ++ show (AnotherType.foo bar)
```
Finally, since we're delving into language extensions, why not just allow record access with a dot syntax directly with [`OverloadedRecordDot`](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/overloaded_record_dot.html)?
```haskell
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Main where
import MyType (MyType(..))
import AnotherType (AnotherType(..))
main :: IO ()
main = do
let foo = MyType { foo = 42 }
let bar = AnotherType { foo = "bar" }
putStrLn $ "foo = " ++ show foo.foo
putStrLn $ "bar = " ++ show bar.foo
```
This means there's no need to artificially move around type definitions:
```haskell
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Main where
data MyType = MyType
{ foo :: Int
} deriving (Show)
data AnotherType = AnotherType
{ foo :: String
} deriving (Show)
main :: IO ()
main = do
let foo = MyType { foo = 42 }
let bar = AnotherType { foo = "bar" }
putStrLn $ "foo = " ++ show foo.foo
putStrLn $ "bar = " ++ show bar.foo
```