GHC not able to detect impossible GADT pattern
Simon Peyton Jones
simonpj at microsoft.com
Wed Sep 3 06:21:34 UTC 2014
I believe this is probably an instance of
https://ghc.haskell.org/trac/ghc/ticket/3927
There are numerous other similar tickets, about GHC's inadequate/misleading warnings for non-exhaustive patterns. A selection is
#595, #5728, #3927, #5724, #5762, #4139, #6124, #7669, #322, #8016, #8494, #8853, #8970, #9113.
Tom Schrijvers and colleagues are working on this right now, I'm glad to say.
Please do add your example to #3927, so that we can be sure to use it as a regression test when testing Tom's shiny new version.
Simon
| -----Original Message-----
| From: Glasgow-haskell-users [mailto:glasgow-haskell-users-
| bounces at haskell.org] On Behalf Of Merijn Verstraaten
| Sent: 03 September 2014 06:59
| To: GHC Users List
| Subject: GHC not able to detect impossible GADT pattern
|
| I've been trying to stretch GHC's type system again and somehow managed
| to get myself into a position where GHC warns about a non-exhaustive
| pattern where adding the (according to GHC) missing pattern results in a
| type error (as intended by me). It seems that even with closed type
| families GHC can't infer some patterns can never occur? Complete code to
| reproduce the issue is including below, the non-exhaustive pattern
| happens in the local definitions 'f' of push and pull.
|
| I'm open to suggestions for other approaches.
|
| Kind regards,
| Merijn
|
| {-# LANGUAGE ConstraintKinds #-}
| {-# LANGUAGE DataKinds #-}
| {-# LANGUAGE GADTs #-}
| {-# LANGUAGE RankNTypes #-}
| {-# LANGUAGE ScopedTypeVariables #-}
| {-# LANGUAGE TypeFamilies #-}
| {-# LANGUAGE TypeOperators #-}
| {-# LANGUAGE UndecidableInstances #-}
| module Test where
|
| import Data.Proxy
| import GHC.Exts
|
| data Message
|
| data SocketType = Dealer | Push | Pull
|
| data SocketOperation = Read | Write
|
| type family Restrict (a :: SocketOperation) (as :: [SocketOperation]) ::
| Constraint where
| Restrict a (a ': as) = ()
| Restrict x (a ': as) = Restrict x as
| Restrict x '[] = ("Error!" ~ "Tried to apply a restricted type!")
|
| type family Implements (t :: SocketType) :: [SocketOperation] where
| Implements Dealer = ['Read, Write]
| Implements Push = '[Write]
| Implements Pull = '[ 'Read]
|
| data SockOp :: SocketType -> SocketOperation -> * where
| SRead :: SockOp sock 'Read
| SWrite :: SockOp sock Write
|
| data Socket :: SocketType -> * where
| Socket :: proxy sock
| -> (forall op . Restrict op (Implements sock) => SockOp sock
| op -> Operation op)
| -> Socket sock
|
| type family Operation (op :: SocketOperation) :: * where
| Operation 'Read = IO Message
| Operation Write = Message -> IO ()
|
| class Restrict 'Read (Implements t) => Readable t where
| readSocket :: Socket t -> Operation 'Read
| readSocket (Socket _ f) = f (SRead :: SockOp t 'Read)
|
| instance Readable Dealer
|
| type family Writable (t :: SocketType) :: Constraint where
| Writable Dealer = ()
| Writable Push = ()
|
| dealer :: Socket Dealer
| dealer = Socket (Proxy :: Proxy Dealer) f
| where
| f :: Restrict op (Implements Dealer) => SockOp Dealer op -> Operation
| op
| f SRead = undefined
| f SWrite = undefined
|
| push :: Socket Push
| push = Socket (Proxy :: Proxy Push) f
| where
| f :: Restrict op (Implements Push) => SockOp Push op -> Operation op
| f SWrite = undefined
|
| pull :: Socket Pull
| pull = Socket (Proxy :: Proxy Pull) f
| where
| f :: Restrict op (Implements Pull) => SockOp Pull op -> Operation op
| f SRead = undefined
|
| foo :: IO Message
| foo = readSocket dealer
More information about the Glasgow-haskell-users
mailing list