On Tue, 1 Nov 2016 01:31:55 +0100
Michał Górny <mgo...@gentoo.org> wrote:

Haskell package ecosystem (hackage) encourages
upper version bounds and strict version bounds on
dependencies: http://pvp.haskell.org/

Most of dependencies look like:
    >=foo-1.3 <foo-1.5
    >=bar-2.1 <bar-2.8
    || ( ( >=baz-2.1 <baz-2.8 ) ( >=baz-2.9 <baz-3.1 ) )
Or even:
    ~bar-1.4.2.0

If we want to preserve upstream's versioning (and
we most of the time do). That requires support for
things that portage does not provide in it's current
form.

> Therefore, I would like to ask the following questions:
> 
> 1. How often do you find '~' useful? Do you think there should be
> additional operators that ignore revision part?

Haskell packages occasionally bind to very specific library version.
The set of packages is usually released together because
package author tests against that single set of versions.

 ::gentoo examples:

dev-haskell/haddock/haddock-2.16.1.ebuild:      ~dev-haskell/haddock-api-2.16.1
dev-haskell/hspec/hspec-2.2.1.ebuild:RDEPEND="~dev-haskell/hspec-core-2.2.1:=[profile?]
dev-haskell/hspec/hspec-2.2.1.ebuild:   
~dev-haskell/hspec-discover-2.2.1:=[profile?]

::haskell examples:

dev-haskell/edisoncore/edisoncore-1.2.2.1.ebuild:RDEPEND="~dev-haskell/edisonapi-1.2.2.1:=[profile?]
dev-haskell/ghc-api/ghc-api-7.10.3.ebuild:      ~dev-haskell/binary-0.7.6.1:=
dev-haskell/ghc-api/ghc-api-7.10.3.ebuild:      
~dev-haskell/transformers-0.4.3.0:=
dev-haskell/hledger-web/hledger-web-0.27.ebuild:        
~dev-haskell/hledger-0.27:=[profile?]
dev-haskell/hledger-web/hledger-web-0.27.ebuild:        
~dev-haskell/hledger-lib-0.27:=[profile?]
dev-haskell/hledger/hledger-0.27.ebuild:        
~dev-haskell/hledger-lib-0.27:=[profile?]
dev-haskell/hprotoc/hprotoc-2.4.0.ebuild:       
~dev-haskell/protocol-buffers-2.4.0:=[profile?]
dev-haskell/hprotoc/hprotoc-2.4.0.ebuild:       
~dev-haskell/protocol-buffers-descriptor-2.4.0:=[profile?]
dev-haskell/llvm-general/llvm-general-3.5.1.2.ebuild:RDEPEND="~dev-haskell/llvm-general-pure-3.5.1.0:=[profile?]
dev-haskell/protocol-buffers-descriptor/protocol-buffers-descriptor-2.4.0.ebuild:RDEPEND="~dev-haskell/protocol-buffers-2.4.0:=[profile?]
dev-haskell/yarr/yarr-1.4.0.2.ebuild:   
~dev-haskell/missing-foreign-0.1.1:=[profile?]
dev-lang/elm-make/elm-make-0.17.1-r1.ebuild:    ~dev-lang/elm-compiler-0.17.1:=
dev-lang/elm-meta/elm-meta-0.17.1.ebuild:       ~dev-lang/elm-compiler-${PV}
dev-lang/elm-meta/elm-meta-0.17.1.ebuild:       ~dev-lang/elm-make-${PV}
dev-lang/elm-meta/elm-meta-0.17.1.ebuild:       ~dev-lang/elm-package-${PV}
dev-lang/elm-meta/elm-meta-0.17.1.ebuild:       ~dev-lang/elm-reactor-${PV}
dev-lang/elm-meta/elm-meta-0.17.1.ebuild:       ~dev-lang/elm-repl-${PV}
dev-lang/elm-package/elm-package-0.17.1-r2.ebuild:      
~dev-lang/elm-compiler-0.17.1:=[profile?]
dev-lang/elm-reactor/elm-reactor-0.17.1.ebuild: ~dev-lang/elm-compiler-0.17.1:=
dev-lang/elm-reactor/elm-reactor-0.17.1.ebuild: ~dev-lang/elm-make-${PV}
dev-lang/elm-repl/elm-repl-0.17.1.ebuild:       ~dev-lang/elm-compiler-0.17.1:=
sci-mathematics/agda/agda-9999.ebuild:  ~dev-haskell/edisonapi-1.3:=[profile?]

> 2. How often do you find '=...*' wildcard syntax useful? To what
> purpose do you use it? Do you find its behavior confusing [1]?

haskell used to optimise ranged dependencies of style
    >=foo-2 && <foo-3
into
    =foo-2*
but now we always generate 
    >=foo-2 && <foo-3
to ease ebuild patching when package is ported to foo-3
dependency.

Special care must be taken when 'foo' is slotted but we
try not to slot things.

> 4. What are the common tasks that you find unnecessarily complex /
> lengthy with the current version specifications?

Problem 1:

Sometimes upstream decides that one of their dependencies
is broken on a version range (package compiles but does
horrible things due to accidental semantic change in a dependency)

Common example is aeson. Upstream dependency looks like:
    || ( ( >=aeson-0.5 <aeson-0.10 )
          ( >=aeson-0.11 <aeson-1.2 ) )

While it works there is no matching syntax
for the same behaviour but with added rebuild on upgrade.

This is not accepted nowadays:
    || ( ( >=aeson-0.5:= <aeson-0.10:= )
          ( >=aeson-0.11:= <aeson-1.2:= ) )

Currently we avoid it by simplifying the depend down to
latest available or throw away broken versions from tree
completely if the breakage is common enough:

         ( >=aeson-0.11:= <aeson-1.2:= )
or
         ( >=aeson-0.5:= <aeson-1.2:= )

Problem 2:

Haskell ABI it a SUM of:
- ABIs of its dependency libraries
- own exports
Library version is a part of that library ABI.
Thus library ABI is guaranteed to change every library release.

It means that once end user merges a library version bump
user needs to rebuild all library's transitive reverse dependencies.
Sometimes library is deep in the dependency chain (5-10 levels deep).

There is no way to express that style of dependency in portage:
    https://bugs.gentoo.org/show_bug.cgi?id=449094
and app-admin/haskell-updater is still a needed thing to restore
world sanity after a library upgrade.

-- 

  Sergei

Attachment: pgpk8L4QpH3E0.pgp
Description: Цифровая подпись OpenPGP

Reply via email to