├── Setup.hs ├── .gitignore ├── .gitmodules ├── ChangeLog.md ├── stack.yaml ├── README.md ├── src └── Data │ └── Generics │ └── Labels.hs ├── LICENSE ├── generic-lens-labels.cabal └── .travis.yml /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.stack-work 2 | /dist 3 | /dist-newstyle 4 | /.cabal-sandbox 5 | cabal.sandbox.config -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "generic-lens"] 2 | path = generic-lens 3 | url = https://github.com/kcsongor/generic-lens 4 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # Revision history for generic-lens-labels 2 | 3 | ## 0.1.0.0 -- YYYY-mm-dd 4 | 5 | * First version. Released on an unsuspecting world. 6 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-10.3 2 | 3 | packages: 4 | - '.' 5 | - generic-lens 6 | 7 | # The following is useful for testing with hackage versions of generic-lens 8 | extra-deps: 9 | # - generic-lens-0.3.0.0 10 | # - generic-lens-0.3.0.1 11 | # - generic-lens-0.4.0.0 12 | # - generic-lens-0.4.1.0 13 | # - generic-lens-0.5.0.0 14 | # - generic-lens-0.5.1.0 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | master build: [![Build Status](https://travis-ci.org/duog/generic-lens-labels.svg?branch=master)](https://travis-ci.org/duog/generic-lens-labels) 2 | 3 | develop build: [![Build Status](https://travis-ci.org/duog/generic-lens-labels.svg?branch=develop)](https://travis-ci.org/duog/generic-lens-labels) 4 | 5 | develop branch 6 | ================== 7 | 8 | I may rebase develop from time to time, let me know if that's causing you problems. 9 | 10 | Summary 11 | ======= 12 | 13 | This package provides the module `Data.Generic.Labels`, which provides an `IsLabel` instance 14 | allowing one to use `OverloadedLabels` to access field lenses from the [generic-lens](https://github.com/kcsongor/generic-lens) library. 15 | 16 | As the `IsLabel` instance provided is necessarily orphan, your code will break if you depend on 17 | this library and any other library that provides an orphan `IsLabel` instance at the same 18 | time. As such, this should be considered a toy. 19 | 20 | Example: 21 | ======== 22 | 23 | ```haskell 24 | {-# LANGUAGE OverloadedLabels, DeriveGeneric #- } 25 | 26 | module Example 27 | 28 | import Data.Generics.Labels() 29 | import GHC.Generics 30 | import Control.Lens 31 | 32 | data Foo = Foo {bar :: Int} deriving (Generic) 33 | 34 | _bar :: Lens' Foo Int 35 | _bar = #bar 36 | ``` 37 | -------------------------------------------------------------------------------- /src/Data/Generics/Labels.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP, TypeFamilies, TypeApplications,ScopedTypeVariables 2 | , FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} 3 | {-# OPTIONS_GHC -Wno-orphans #-} 4 | module Data.Generics.Labels 5 | () where 6 | 7 | import Data.Generics.Product 8 | import GHC.OverloadedLabels 9 | 10 | {- 11 | example: 12 | 13 | data Foo = Foo {bar :: Int} deriving (Generic) 14 | 15 | _bar :: Lens' Foo Int 16 | _bar = #bar 17 | 18 | -} 19 | 20 | {- 21 | This is the instance head that seems to give the best type inference. 22 | -} 23 | 24 | #if MIN_VERSION_generic_lens(0,5,0) 25 | 26 | #if (__GLASGOW_HASKELL__ < 802) 27 | 28 | instance (HasField x s t a b, Functor f, lens ~ ((a -> f b) -> s -> f t)) => 29 | IsLabel x lens where 30 | fromLabel _ = field @ x 31 | 32 | #else 33 | -- __GLASGOW_HASKELL 34 | 35 | instance (HasField x s t a b, Functor f, lens ~ ((a -> f b) -> s -> f t)) => 36 | IsLabel x lens where 37 | fromLabel = field @ x 38 | 39 | #endif 40 | -- __GLASGOW_HASKELL 41 | 42 | #elif (__GLASGOW_HASKELL__ < 802) 43 | -- MIN_VERSION_generic_lens 44 | 45 | instance (HasField x a s, Functor f, lens ~ ((a -> f a) -> s -> f s)) => 46 | IsLabel x lens where 47 | fromLabel _ = field @ x 48 | 49 | #else 50 | -- __GLASGOW_HASKELL 51 | 52 | instance (HasField x a s, Functor f, lens ~ ((a -> f a) -> s -> f s)) => 53 | IsLabel x lens where 54 | fromLabel = field @ x 55 | 56 | #endif 57 | -- __GLASGOW_HASKELL 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Douglas Wilson 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Douglas Wilson nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /generic-lens-labels.cabal: -------------------------------------------------------------------------------- 1 | -- Initial generic-lens-labels.cabal generated by cabal init. For further 2 | -- documentation, see http://haskell.org/cabal/users-guide/ 3 | 4 | name: generic-lens-labels 5 | version: 0.1.0.2 6 | 7 | synopsis: GHC.OverloadedLabels.IsLabel instance for lenses from ghc-generics 8 | description: 9 | Provides an orphan GHC.OverloadedLabels.IsLabel instance for lenses from 10 | ghc-generics. All effort is taken to play as nicely as possible with other 11 | IsLabel instances -- however orphan instances are inherently problematic. 12 | Please do not depend on this package from any hackage libraries. 13 | category: Generics, Records, Lens, OverloadeLabels 14 | 15 | copyright: Copyright (C) 2017-2018 Douglas Wilson 16 | license: BSD3 17 | license-file: LICENSE 18 | 19 | author: Douglas Wilson 20 | maintainer: douglas.wilson@gmail.com 21 | homepage: https://github.com/duog/generic-lens-labels 22 | bug-reports: https://github.com/duog/generic-lens-labels/issues 23 | 24 | build-type: Simple 25 | cabal-version: >= 1.10 26 | 27 | -- TODO 28 | tested-With: GHC == 8.0.2, GHC == 8.2.2 29 | 30 | build-type: Simple 31 | extra-source-files: ChangeLog.md 32 | cabal-version: >=1.10 33 | 34 | library 35 | exposed-modules: Data.Generics.Labels 36 | -- other-modules: 37 | -- other-extensions: 38 | build-depends: base >=4.9 && <4.11, 39 | generic-lens >= 0.3.0 && < 0.5.2 40 | hs-source-dirs: src 41 | default-language: Haskell2010 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # This is the complex Travis configuration, which is intended for use 2 | # on open source libraries which need compatibility across multiple GHC 3 | # versions, must work with cabal-install, and should be 4 | # cross-platform. For more information and other options, see: 5 | # 6 | # https://docs.haskellstack.org/en/stable/travis_ci/ 7 | # 8 | # Copy these contents into the root directory of your Github project in a file 9 | # named .travis.yml 10 | 11 | # Use new container infrastructure to enable caching 12 | sudo: false 13 | 14 | # Do not choose a language; we provide our own build tools. 15 | language: generic 16 | 17 | # Caching so the next build will be fast too. 18 | cache: 19 | directories: 20 | - $HOME/.ghc 21 | - $HOME/.cabal 22 | - $HOME/.stack 23 | 24 | # The different configurations we want to test. We have BUILD=cabal which uses 25 | # cabal-install, and BUILD=stack which uses Stack. More documentation on each 26 | # of those below. 27 | # 28 | # We set the compiler values here to tell Travis to use a different 29 | # cache file per set of arguments. 30 | # 31 | # If you need to have different apt packages for each combination in the 32 | # matrix, you can use a line such as: 33 | # addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}} 34 | matrix: 35 | include: 36 | # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See: 37 | # https://github.com/hvr/multi-ghc-travis 38 | #- env: BUILD=cabal GHCVER=7.0.4 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 39 | # compiler: ": #GHC 7.0.4" 40 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.0.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 41 | #- env: BUILD=cabal GHCVER=7.2.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 42 | # compiler: ": #GHC 7.2.2" 43 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 44 | #- env: BUILD=cabal GHCVER=7.4.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 45 | # compiler: ": #GHC 7.4.2" 46 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 47 | #- env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7 48 | # compiler: ": #GHC 7.6.3" 49 | # addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 50 | #- env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18 HAPPYVER=1.19.5 ALEXVER=3.1.7 51 | # compiler: ": #GHC 7.8.4" 52 | # addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 53 | # - env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 HAPPYVER=1.19.5 ALEXVER=3.1.7 54 | # compiler: ": #GHC 7.10.3" 55 | # addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 56 | - env: BUILD=cabal GHCVER=8.0.2 CABALVER=1.24 HAPPYVER=1.19.5 ALEXVER=3.1.7 57 | compiler: ": #GHC 8.0.2" 58 | addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 59 | - env: BUILD=cabal GHCVER=8.2.2 CABALVER=2.0 HAPPYVER=1.19.5 ALEXVER=3.1.7 60 | compiler: ": #GHC 8.2.2" 61 | addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 62 | 63 | # Build with the newest GHC and cabal-install. This is an accepted failure, 64 | # see below. 65 | - env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7 66 | compiler: ": #GHC HEAD" 67 | addons: {apt: {packages: [cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}} 68 | 69 | # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS 70 | # variable, such as using --stack-yaml to point to a different file. 71 | - env: BUILD=stack ARGS="" 72 | compiler: ": #stack default" 73 | addons: {apt: {packages: [libgmp-dev]}} 74 | 75 | - env: BUILD=stack ARGS="--resolver lts-9" 76 | compiler: ": #stack 8.0.2" 77 | addons: {apt: {packages: [libgmp-dev]}} 78 | 79 | - env: BUILD=stack ARGS="--resolver lts-10" 80 | compiler: ": #stack 8.2.2" 81 | addons: {apt: {packages: [libgmp-dev]}} 82 | 83 | # Nightly builds are allowed to fail 84 | - env: BUILD=stack ARGS="--resolver nightly" 85 | compiler: ": #stack nightly" 86 | addons: {apt: {packages: [libgmp-dev]}} 87 | 88 | # Build on macOS in addition to Linux 89 | - env: BUILD=stack ARGS="" 90 | compiler: ": #stack default osx" 91 | os: osx 92 | 93 | # Travis includes an macOS which is incompatible with GHC 7.8.4 94 | #- env: BUILD=stack ARGS="--resolver lts-2" 95 | # compiler: ": #stack 7.8.4 osx" 96 | # os: osx 97 | 98 | - env: BUILD=stack ARGS="--resolver lts-9" 99 | compiler: ": #stack 8.0.2 osx" 100 | os: osx 101 | 102 | - env: BUILD=stack ARGS="--resolver lts-10" 103 | compiler: ": #stack 8.2.2 osx" 104 | os: osx 105 | 106 | - env: BUILD=stack ARGS="--resolver nightly" 107 | compiler: ": #stack nightly osx" 108 | os: osx 109 | 110 | allow_failures: 111 | - env: BUILD=cabal CABALVER=head GHCVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7 112 | - env: BUILD=stack ARGS="--resolver nightly" 113 | 114 | before_install: 115 | # Using compiler above sets CC to an invalid value, so unset it 116 | - unset CC 117 | 118 | # We want to always allow newer versions of packages when building on GHC HEAD 119 | - CABALARGS="" 120 | - if [ "x$GHCVER" = "xhead" ]; then CABALARGS=--allow-newer; fi 121 | 122 | # Download and unpack the stack executable 123 | - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:/opt/alex/$ALEXVER/bin:/opt/happy/$HAPPYVER/bin:$HOME/.cabal/bin:$PATH 124 | - mkdir -p ~/.local/bin 125 | - | 126 | if [ `uname` = "Darwin" ] 127 | then 128 | travis_retry curl --insecure -L https://www.stackage.org/stack/osx-x86_64 | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin 129 | else 130 | travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack' 131 | fi 132 | 133 | # Use the more reliable S3 mirror of Hackage 134 | mkdir -p $HOME/.cabal 135 | echo 'remote-repo: hackage.haskell.org:http://hackage.fpcomplete.com/' > $HOME/.cabal/config 136 | echo 'remote-repo-cache: $HOME/.cabal/packages' >> $HOME/.cabal/config 137 | 138 | if [ "$CABALVER" != "1.16" ] 139 | then 140 | echo 'jobs: $ncpus' >> $HOME/.cabal/config 141 | fi 142 | 143 | install: 144 | - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]" 145 | - if [ -f configure.ac ]; then autoreconf -i; fi 146 | - | 147 | set -ex 148 | case "$BUILD" in 149 | stack) 150 | # Add in extra-deps for older snapshots, as necessary 151 | stack --no-terminal --install-ghc $ARGS test --bench --dry-run || ( \ 152 | stack --no-terminal $ARGS build cabal-install && \ 153 | stack --no-terminal $ARGS solver --update-config) 154 | 155 | # Build the dependencies 156 | stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies 157 | ;; 158 | cabal) 159 | cabal --version 160 | travis_retry cabal update 161 | 162 | # Get the list of packages from the stack.yaml file. Note that 163 | # this will also implicitly run hpack as necessary to generate 164 | # the .cabal files needed by cabal-install. 165 | PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@') 166 | 167 | cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES 168 | ;; 169 | esac 170 | set +ex 171 | 172 | script: 173 | - | 174 | set -ex 175 | case "$BUILD" in 176 | stack) 177 | stack --no-terminal $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps 178 | ;; 179 | cabal) 180 | cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES 181 | 182 | ORIGDIR=$(pwd) 183 | for dir in $PACKAGES 184 | do 185 | cd $dir 186 | cabal check || [ "$CABALVER" == "1.16" ] 187 | cabal sdist 188 | PKGVER=$(cabal info . | awk '{print $2;exit}') 189 | SRC_TGZ=$PKGVER.tar.gz 190 | cd dist 191 | tar zxfv "$SRC_TGZ" 192 | cd "$PKGVER" 193 | cabal configure --enable-tests 194 | cabal build 195 | cabal test 196 | cd $ORIGDIR 197 | done 198 | ;; 199 | esac 200 | set +ex 201 | --------------------------------------------------------------------------------