Coercing existential according to type-level Maybe (re-post from h-beginners)

(as suggested, i'm re-asking here) Hi. I've tried to write a function to coerce existential value according to type stored in type-level 'Maybe' (i.e. 'Just or 'Nothing).
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce
class FromTypeMaybe k where type ToType k fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k)
--instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe t) where instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = t fromTypeMaybe f _ x = Nothing
instance forall (t :: Type). FromTypeMaybe ('Just t :: Maybe Type) where type ToType ('Just t) = t fromTypeMaybe f _ x = Just (f x)
data Any where Any :: a -> Any
unAny :: Any -> t unAny (Any x) = unsafeCoerce x
This works as far as i can see *Main> fromTypeMaybe unAny (Proxy @('Just Int)) (Any 3) Just 3 *Main> fromTypeMaybe unAny (Proxy @'Nothing) undefined Nothing but i don't understand how 'Nothing instance works: type kind kind? vvv vvvvvv vvv instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe t) where type ToType 'Nothing = t ^^^ type (in case alignment breaks: variable 't' in forall is type-variable with kind 'Type', but in "Maybe t" in instance head it's used as kind-variable. And then in associated type-family the same variable 't' is used as type-variable again). If i try to write "'Nothing"'s kind as 'Maybe Type' (in the same manner as 'Just has) instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe Type) where i get an error: 1.lhs:21:3: error: • Type variable ‘t’ is mentioned in the RHS, but not bound on the LHS of the family instance • In the type instance declaration for ‘ToType’ In the instance declaration for ‘FromTypeMaybe ('Nothing :: Maybe Type)’ | 21 | > instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe Type) where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... Well, i'm not sure, that understand why 'forall' in instance head may not be used as family's LHS, but.. that's another question. On the other hand, if i try to write 'Just instance using type-variable 't' as kind-variable (in the same manner as 'Nothing has): instance forall (t :: Type). FromTypeMaybe ('Just t :: Maybe t) where i get an error too: 1.lhs:25:47: error: • Expected kind ‘Maybe t’, but ‘'Just t’ has kind ‘Maybe *’ • In the first argument of ‘FromTypeMaybe’, namely ‘('Just t :: Maybe t)’ In the instance declaration for ‘FromTypeMaybe ('Just t :: Maybe t)’ | 25 | > instance forall (t :: Type). FromTypeMaybe ('Just t :: Maybe t) where Well, that's also probably expected, because though i've declared type-variable 't' with kind 'Type' in forall, due to 'DataKinds' extension type 't' is also promoted to kind 't' and, thus, by using ('Just t :: Maybe t) i say, that ('Just t) should have kind 'Maybe t', not 'Maybe Type', which it really has. But if that's so, how working 'Nothing instance instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe t) where may work at all? It has the same problem as 'Just instance above: type-variable 't' is promoted to kind 't' and 'Nothing will have kind 'Maybe t' instead of 'Maybe Type' ?

Hi Dmitriy, Fun stuff here! - Have you looked at https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Dynamic.html ? That may have the functionality you're looking for. It's quite a bit simpler than the construction you're building, but it might satisfy your eventual use-case. - GHC does not distinguish between types and kinds, since GHC 8.0. Much literature about Haskell continues to make this distinction, including GHC's own error messages (at some implementation challenge, even). This is because, most of the time, programs don't cross the line between types and kinds, and this distinction can be helpful. However, your code does shuttle ideas back and forth across the line, and so the distinction is harmful. Bottom line here: treat types and kinds as synonyms. The design of Haskell does, internally. - I think the crux of your question is why (Just t :: Maybe t) fails to type-check. We can see this in the type of Just: Just :: forall (a :: Type). a -> Maybe a. When we write `Just t` (for `t :: Type`), GHC sees `Just @Type t`, supplying the invisible instantiation for the `forall (a :: Type)` argument in Just's type. We can now see that `Just @Type t` will have type `Maybe Type`, just by substituting in Just's type. So saying `Just t :: Maybe t` will be rejected. - On the other hand, `Nothing :: Maybe t` is fine. We have `Nothing :: forall (a :: Type). Maybe a`, and so `Nothing :: Maybe t` really means `Nothing @t :: Maybe t`, and all is well. I worry that there is more in your email that I haven't answered here. If so, please write back! Richard
On Dec 30, 2021, at 9:50 AM, Dmitriy Matrosov
wrote: (as suggested, i'm re-asking here)
Hi.
I've tried to write a function to coerce existential value according to type stored in type-level 'Maybe' (i.e. 'Just or 'Nothing).
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce
class FromTypeMaybe k where type ToType k fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k)
--instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe t) where instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = t fromTypeMaybe f _ x = Nothing
instance forall (t :: Type). FromTypeMaybe ('Just t :: Maybe Type) where type ToType ('Just t) = t fromTypeMaybe f _ x = Just (f x)
data Any where Any :: a -> Any
unAny :: Any -> t unAny (Any x) = unsafeCoerce x
This works as far as i can see
*Main> fromTypeMaybe unAny (Proxy @('Just Int)) (Any 3) Just 3 *Main> fromTypeMaybe unAny (Proxy @'Nothing) undefined Nothing
but i don't understand how 'Nothing instance works:
type kind kind? vvv vvvvvv vvv instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe t) where type ToType 'Nothing = t ^^^ type
(in case alignment breaks: variable 't' in forall is type-variable with kind 'Type', but in "Maybe t" in instance head it's used as kind-variable. And then in associated type-family the same variable 't' is used as type-variable again).
If i try to write "'Nothing"'s kind as 'Maybe Type' (in the same manner as 'Just has)
instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe Type) where
i get an error:
1.lhs:21:3: error: • Type variable ‘t’ is mentioned in the RHS, but not bound on the LHS of the family instance • In the type instance declaration for ‘ToType’ In the instance declaration for ‘FromTypeMaybe ('Nothing :: Maybe Type)’ | 21 | > instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe Type) where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
Well, i'm not sure, that understand why 'forall' in instance head may not be used as family's LHS, but.. that's another question. On the other hand, if i try to write 'Just instance using type-variable 't' as kind-variable (in the same manner as 'Nothing has):
instance forall (t :: Type). FromTypeMaybe ('Just t :: Maybe t) where
i get an error too:
1.lhs:25:47: error: • Expected kind ‘Maybe t’, but ‘'Just t’ has kind ‘Maybe *’ • In the first argument of ‘FromTypeMaybe’, namely ‘('Just t :: Maybe t)’ In the instance declaration for ‘FromTypeMaybe ('Just t :: Maybe t)’ | 25 | > instance forall (t :: Type). FromTypeMaybe ('Just t :: Maybe t) where
Well, that's also probably expected, because though i've declared type-variable 't' with kind 'Type' in forall, due to 'DataKinds' extension type 't' is also promoted to kind 't' and, thus, by using ('Just t :: Maybe t) i say, that ('Just t) should have kind 'Maybe t', not 'Maybe Type', which it really has.
But if that's so, how working 'Nothing instance
instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe t) where
may work at all? It has the same problem as 'Just instance above: type-variable 't' is promoted to kind 't' and 'Nothing will have kind 'Maybe t' instead of 'Maybe Type' ? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Hi, Richard.
- Have you looked at https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Dynamic.html ? That may have the functionality you're looking for. It's quite a bit simpler than the construction you're building, but it might satisfy your eventual use-case.
Not yet. In fact, i don't have any particular use-case, i'm just reading "thinking with types" book and tried to experiment a little. But anyway, i'll look at this package, thanks!
- GHC does not distinguish between types and kinds, since GHC 8.0. Much literature about Haskell continues to make this distinction, including GHC's own error messages (at some implementation challenge, even). This is because, most of the time, programs don't cross the line between types and kinds, and this distinction can be helpful. However, your code does shuttle ideas back and forth across the line, and so the distinction is harmful. Bottom line here: treat types and kinds as synonyms. The design of Haskell does, internally.
So.. does this mean that there are only two "things" now: "something" and "type of something". And this "something" may be either value or type. And when "something" is type, it's type is what was previously called kind? And the exact same type variable may denote the type of both "something"-s (values and types) at the same time (i.e. in the one expression)?
- I think the crux of your question is why (Just t :: Maybe t) fails to type-check. We can see this in the type of Just: Just :: forall (a :: Type). a -> Maybe a. When we write `Just t` (for `t :: Type`), GHC sees `Just @Type t`, supplying the invisible instantiation for the `forall (a :: Type)` argument in Just's type. We can now see that `Just @Type t` will have type `Maybe Type`, just by substituting in Just's type. So saying `Just t :: Maybe t` will be rejected.
- On the other hand, `Nothing :: Maybe t` is fine. We have `Nothing :: forall (a :: Type). Maybe a`, and so `Nothing :: Maybe t` really means `Nothing @t :: Maybe t`, and all is well.
Thanks a lot, I think that I understand now. And does the error: coerce-existential-with-type-level-maybe.lhs:22:3: error: • Type variable ‘t’ is mentioned in the RHS, but not bound on the LHS of the family instance • In the type instance declaration for ‘ToType’ In the instance declaration for ‘FromTypeMaybe ('Nothing @Type)’ | 22 | > instance forall (t :: Type). FromTypeMaybe ('Nothing @Type) where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^... when i try to apply 'Nothing to @Type instead of @t occurs, because full form of associated type family is type ToType ('Nothing @Type) = t and variable 't' becomes unbound?
I worry that there is more in your email that I haven't answered here. If so, please write back!
Richard

On Fri, Dec 31, 2021 at 04:33:28PM +0300, Dmitriy Matrosov wrote:
Thanks a lot, I think that I understand now. And does the error:
coerce-existential-with-type-level-maybe.lhs:22:3: error: • Type variable ‘t’ is mentioned in the RHS, but not bound on the LHS of the family instance • In the type instance declaration for ‘ToType’ In the instance declaration for ‘FromTypeMaybe ('Nothing @Type)’ | 22 | > instance forall (t :: Type). FromTypeMaybe ('Nothing @Type) where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
The error is a technicality, it goes away if you give `Nothing` an explicit type (kind): instance forall (t :: Type). FromTypeMaybe ('Nothing :: Maybe t) where type ToType ('Nothing :: Maybe t) = t fromTypeMaybe f _ x = Nothing -- Viktor.

On Dec 31, 2021, at 8:33 AM, Dmitriy Matrosov
wrote: - GHC does not distinguish between types and kinds, since GHC 8.0. Much literature about Haskell continues to make this distinction, including GHC's own error messages (at some implementation challenge, even). This is because, most of the time, programs don't cross the line between types and kinds, and this distinction can be helpful. However, your code does shuttle ideas back and forth across the line, and so the distinction is harmful. Bottom line here: treat types and kinds as synonyms. The design of Haskell does, internally.
So.. does this mean that there are only two "things" now: "something" and "type of something". And this "something" may be either value or type. And when "something" is type, it's type is what was previously called kind?
I would say Haskell has terms and types. It also has two relations: type-of-term and type-of-type. The type of a term (using the type-of-term relation) connects a term to a type. The type of a type (using the type-of-type relation) connects a type with another type. Some would say that the type-of-type relation connects a type with a kind, but "kind" is really just a synonym for "type". The design of Haskell has arranged that, for data constructors, the type-of-term relation and the type-of-type relation coincide. That is, the phrase `Just :: forall a. a -> Maybe a` is true both when `Just` is a term (and we're talking about the type-of-term relation) and when `Just` is a type (and we're talking about the type-of-type relation).
And the exact same type variable may denote the type of both "something"-s (values and types) at the same time (i.e. in the one expression)?
I think so -- I'm not sure I understand your phrasing fully. Because types and kinds are the same, one type variable may be used both in a type-of-a-term and in the type-of-a-type.
And does the error:
coerce-existential-with-type-level-maybe.lhs:22:3: error: • Type variable ‘t’ is mentioned in the RHS, but not bound on the LHS of the family instance • In the type instance declaration for ‘ToType’ In the instance declaration for ‘FromTypeMaybe ('Nothing @Type)’ | 22 | > instance forall (t :: Type). FromTypeMaybe ('Nothing @Type) where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
when i try to apply 'Nothing to @Type instead of @t occurs, because full form of associated type family is
type ToType ('Nothing @Type) = t
and variable 't' becomes unbound?
I wouldn't quite say t is unbound there -- it refers to the t in the instance head. What's more troublesome is that, when GHC is trying to reduce `ToType (Nothing @Type)`, it has no way of knowing what `t` is. This is why GHC requires that all variables mentioned in the RHS of an associated type equation are also mentioned on the left. I hope this helps! Richard

On 1/3/22 5:26 PM, Richard Eisenberg wrote:
And does the error:
coerce-existential-with-type-level-maybe.lhs:22:3: error: • Type variable ‘t’ is mentioned in the RHS, but not bound on the LHS of the family instance • In the type instance declaration for ‘ToType’ In the instance declaration for ‘FromTypeMaybe ('Nothing @Type)’ | 22 | > instance forall (t :: Type). FromTypeMaybe ('Nothing @Type) where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
when i try to apply 'Nothing to @Type instead of @t occurs, because full form of associated type family is
type ToType ('Nothing @Type) = t
and variable 't' becomes unbound?
I wouldn't quite say t is unbound there -- it refers to the t in the instance head. What's more troublesome is that, when GHC is trying to reduce `ToType (Nothing @Type)`, it has no way of knowing what `t` is. This is why GHC requires that all variables mentioned in the RHS of an associated type equation are also mentioned on the left.
Hi, Richard. I thought, that my 'FromTypeMaybe' works, but it turns out not always. So, to recap:
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce import qualified GHC.Types as GHC.Types
class FromTypeMaybe k where type ToType k fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k)
instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where --type ToType 'Nothing = GHC.Types.Any type ToType 'Nothing = t fromTypeMaybe f _ x = Nothing
instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where type ToType ('Just t) = t fromTypeMaybe f _ x = Just (f x)
then i've written a little more:
type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail:: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
insertAny :: t -> [AnyData] -> [AnyData] insertAny x zs = AnyData x : zs
headAny :: forall ts . FromTypeMaybe (MaybeHead ts) => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) headAny _ [] = Nothing headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x
And now it works, when type-level list is explicitly specified, like: *Main> headAny (Proxy @'[]) $ insertAny 1 $ insertAny True [] Nothing *Main> headAny (Proxy @'[Int]) $ insertAny 1 $ insertAny True [] Just 1 *Main> headAny (Proxy @'[Int, Bool]) $ insertAny 1 $ insertAny True [] Just 1 but if i use 'Tail' type-function first, it works only in two cases: for list with 2 or more elements *Main> :t headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] :: Maybe Int *Main> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] Just 1 and empty list *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :: Maybe t *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] Nothing But for list with 1 element it does not work *Main> :t headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] :: Maybe * *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] <interactive>:246:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it I think, that understand the problem, but yet don't know how to fix it. If i evaluate types, i get for 2-elements list *Main> :k! Tail '[Bool, Int] Tail '[Bool, Int] :: [*] = '[Int] *Main> :k! MaybeHead (Tail '[Bool, Int]) MaybeHead (Tail '[Bool, Int]) :: Maybe * = 'Just Int *Main> :k! ToType (MaybeHead (Tail '[Bool, Int])) ToType (MaybeHead (Tail '[Bool, Int])) :: * = Int for 1-element list *Main> :k! Tail '[Bool] Tail '[Bool] :: [*] = '[] *Main> :k! MaybeHead (Tail '[Bool]) MaybeHead (Tail '[Bool]) :: Maybe * = 'Nothing *Main> :k! ToType (MaybeHead (Tail '[Bool])) ToType (MaybeHead (Tail '[Bool])) :: * = * and for empty list *Main> :k! Tail '[] Tail '[] :: [t] = '[] *Main> :k! MaybeHead (Tail '[]) MaybeHead (Tail '[]) :: Maybe t = 'Nothing *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any Thus, for 1-element case in type-family 'Tail' type-of-type variable t gets instantiated to '*', because there is one element in list ('Bool' in the example) and its type (kind) is '*'. Then this type '*' goes through 'MaybeHead' and i get ('Nothing :: Maybe *), and type variable t in 'FromTypeMaybe' instance head also gets instantiated to '*'. And then it's just substituted in 'ToType' RHS. And i end up looking for (Show *) instance. In the empty list case, though, type-of-type variable 't' from 'Tail' remains as type variable till the end. But then (for some reason) GHC replaces it with 'GHC.Types.Any' and (yet more strangely) manages to find 'Show' instances for 'GHC.Types.Any'. When i've tried to check may understanding and changed 'Tail' type to type Tail :: [*] -> [*] the empty list case behaves like the 1-element case before: *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = * *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :: Maybe * *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] <interactive>:309:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it and (not surprisingly) does not work. On the other hand, if i explicitly assign 'GHC.Types.Any' as 'ToType k' RHS in 'Nothing instance instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any then the 1-element case seems to become the same as the (working) empty list case from before *Main> :k! ToType (MaybeHead (Tail '[Bool])) ToType (MaybeHead (Tail '[Bool])) :: * = GHC.Types.Any *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any but GHC still can't find 'Show GHC.Types.Any' instance: *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] <interactive>:327:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘print’ There are instances for similar types: instance Show base-4.14.3.0:Data.Semigroup.Internal.Any -- Defined in ‘base-4.14.3.0:Data.Semigroup.Internal’ • In a stmt of an interactive GHCi command: print it *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] <interactive>:328:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘print’ There are instances for similar types: instance Show base-4.14.3.0:Data.Semigroup.Internal.Any -- Defined in ‘base-4.14.3.0:Data.Semigroup.Internal’ • In a stmt of an interactive GHCi command: print it Well, probably, the problem is that i don't understand what is 'GHC.Types.Any' and how GHC finds 'Show' instance for it ('Any types' notes in GHC.Builtin.Types does not explain much; probably, i need to read the book further instead..) And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) instance. Thanks.

On 1/17/22 6:49 PM, Dmitriy Matrosov wrote:
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce import qualified GHC.Types as GHC.Types
class FromTypeMaybe k where type ToType k fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k)
instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where --type ToType 'Nothing = GHC.Types.Any type ToType 'Nothing = t fromTypeMaybe f _ x = Nothing
instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where type ToType ('Just t) = t fromTypeMaybe f _ x = Just (f x)
then i've written a little more:
type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail:: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
insertAny :: t -> [AnyData] -> [AnyData] insertAny x zs = AnyData x : zs
headAny :: forall ts . FromTypeMaybe (MaybeHead ts) => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) headAny _ [] = Nothing headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x
And now it works, when type-level list is explicitly specified, like:
*Main> headAny (Proxy @'[]) $ insertAny 1 $ insertAny True [] Nothing *Main> headAny (Proxy @'[Int]) $ insertAny 1 $ insertAny True [] Just 1 *Main> headAny (Proxy @'[Int, Bool]) $ insertAny 1 $ insertAny True [] Just 1
but if i use 'Tail' type-function first, it works only in two cases:
for list with 2 or more elements
*Main> :t headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] :: Maybe Int *Main> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] Just 1
and empty list
*Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :: Maybe t *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] Nothing
But for list with 1 element it does not work
*Main> :t headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] :: Maybe * *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True []
<interactive>:246:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it
.....
And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) instance.
I think, i've fixed everything. Eventually, it was very simple.
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce
class FromTypeMaybe2 k t where fromTypeMaybe2 :: (a -> t) -> Proxy k -> a -> Maybe t
instance FromTypeMaybe2 'Nothing t where fromTypeMaybe2 f _ _ = Nothing
instance (t ~ t') => FromTypeMaybe2 ('Just t) t' where fromTypeMaybe2 f _ x = Just (f x)
headAny2 :: forall t ts . FromTypeMaybe2 (MaybeHead ts) t => Proxy ts -> [AnyData] -> Maybe t headAny2 _ [] = Nothing headAny2 _ (x : xs) = fromTypeMaybe2 unAny (Proxy @(MaybeHead ts)) x
type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail:: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
And now everything works: *Main> headAny2 (Proxy @'[]) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @'[Int]) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @'[Int, Bool]) $ [AnyData 1, AnyData True] Just 1 and *Main> headAny2 (Proxy @(Tail '[Bool, Int])) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @(Tail '[Bool])) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @(Tail '[])) $ [AnyData 1, AnyData True] Nothing The only question, that remains is why defining 'Nothing resulting type to be 'GHC.Types.Any' in previous implementation instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any does not fix it?

I was at a conference last week and didn't have time to respond... but now that I return to this, I still don't really understand what your question is. Sorry! I think this will help: Why invoke GHC.Types.Any at all? What are you hoping to accomplish with GHC.Types.Any? Thanks, Richard
On Jan 18, 2022, at 8:10 AM, Dmitriy Matrosov
wrote: On 1/17/22 6:49 PM, Dmitriy Matrosov wrote:
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce import qualified GHC.Types as GHC.Types
class FromTypeMaybe k where type ToType k fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k) instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where --type ToType 'Nothing = GHC.Types.Any type ToType 'Nothing = t fromTypeMaybe f _ x = Nothing instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where type ToType ('Just t) = t fromTypeMaybe f _ x = Just (f x) then i've written a little more: type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail:: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
insertAny :: t -> [AnyData] -> [AnyData] insertAny x zs = AnyData x : zs
headAny :: forall ts . FromTypeMaybe (MaybeHead ts) => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) headAny _ [] = Nothing headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x And now it works, when type-level list is explicitly specified, like: *Main> headAny (Proxy @'[]) $ insertAny 1 $ insertAny True [] Nothing *Main> headAny (Proxy @'[Int]) $ insertAny 1 $ insertAny True [] Just 1 *Main> headAny (Proxy @'[Int, Bool]) $ insertAny 1 $ insertAny True [] Just 1 but if i use 'Tail' type-function first, it works only in two cases: for list with 2 or more elements *Main> :t headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] :: Maybe Int *Main> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] Just 1 and empty list *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :: Maybe t *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] Nothing But for list with 1 element it does not work *Main> :t headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] :: Maybe * *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] <interactive>:246:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it ..... And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) instance.
I think, i've fixed everything. Eventually, it was very simple.
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce
class FromTypeMaybe2 k t where fromTypeMaybe2 :: (a -> t) -> Proxy k -> a -> Maybe t
instance FromTypeMaybe2 'Nothing t where fromTypeMaybe2 f _ _ = Nothing
instance (t ~ t') => FromTypeMaybe2 ('Just t) t' where fromTypeMaybe2 f _ x = Just (f x)
headAny2 :: forall t ts . FromTypeMaybe2 (MaybeHead ts) t => Proxy ts -> [AnyData] -> Maybe t headAny2 _ [] = Nothing headAny2 _ (x : xs) = fromTypeMaybe2 unAny (Proxy @(MaybeHead ts)) x
type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail:: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
And now everything works:
*Main> headAny2 (Proxy @'[]) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @'[Int]) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @'[Int, Bool]) $ [AnyData 1, AnyData True] Just 1
and
*Main> headAny2 (Proxy @(Tail '[Bool, Int])) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @(Tail '[Bool])) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @(Tail '[])) $ [AnyData 1, AnyData True] Nothing
The only question, that remains is why defining 'Nothing resulting type to be 'GHC.Types.Any' in previous implementation
instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any
does not fix it? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On 1/26/22 10:38 PM, Richard Eisenberg wrote:
I was at a conference last week and didn't have time to respond... but now that I return to this, I still don't really understand what your question is. Sorry!
I think this will help: Why invoke GHC.Types.Any at all? What are you hoping to accomplish with GHC.Types.Any?
Well, that's more of a theoretical question. As i wrote earlier, i've fixed this example (by using type-class definition similar to IsLabel and without GHC.Types.Any). But anyway, i try to explain shorter. I've had the following code, which defines head function for using on list of existentials and coercing the head back to original type according to type-level list:
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce import qualified GHC.Types as GHC.Types
class FromTypeMaybe k where type ToType k fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k)
instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where --type ToType 'Nothing = GHC.Types.Any type ToType 'Nothing = t fromTypeMaybe f _ x = Nothing
instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where type ToType ('Just t) = t fromTypeMaybe f _ x = Just (f x)
type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail :: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
headAny :: forall ts . FromTypeMaybe (MaybeHead ts) => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) headAny _ [] = Nothing headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x
This code works, when type-level list specified explicitly, like *Main> headAny @('[Int, Bool]) Proxy [AnyData 1, AnyData True] Just 1 but when i use 'Tail' function on type-level list with 1 element, it does not work: *Main> headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] <interactive>:22:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it Though on list with many elements and with empty list everything works: *Main> headAny @(Tail '[]) Proxy [AnyData 1, AnyData True] Nothing When i've tried to understand why, i've noticed some similarities between working empty list case and non-working 1-element case: both these cases work through 'Nothing instance of 'FromTypeMaybe' type class, but type variable t is defined differently: *Main> :k! MaybeHead (Tail '[]) MaybeHead (Tail '[]) :: Maybe t = 'Nothing *Main> :k! MaybeHead (Tail '[Bool]) MaybeHead (Tail '[Bool]) :: Maybe * = 'Nothing So, with empty list type variable t remains unbound, but with 1-element list it is bound to Type. And then (ToType 'Nothing) is defined accordingly: *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any *Main> :k! ToType (MaybeHead (Tail '[Bool])) ToType (MaybeHead (Tail '[Bool])) :: * = * And, no surprise, that there's no (Show Type) instance: *Main> show $ headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] <interactive>:38:1: error: • No instance for (Show *) arising from a use of ‘show’ Until that moment, i understand everything (i think). But then ghc somehow manages to find Show instance for GHC.Types.Any (or may be not, but how does it print result for empty list then?): *Main> show $ headAny @(Tail '[]) Proxy [AnyData 1, AnyData True] "Nothing" And that's the first thing i don't understand: there's should be no Show instance, but still.. Then i thought, that by defining (ToType 'Nothing) to be GHC.Types.Any instead of t: instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any fromTypeMaybe f _ x = Nothing i may fix 1-element case. Type evaluation looked promising: *Main> :k! (MaybeHead (Tail '[])) (MaybeHead (Tail '[])) :: Maybe t = 'Nothing *Main> :k! ToType (MaybeHead (Tail '[])) ToType (MaybeHead (Tail '[])) :: * = GHC.Types.Any but it does not work: *Main> show $ headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True] <interactive>:44:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘show’ *Main> show $ headAny @(Tail '[]) Proxy [AnyData 1, AnyData True] <interactive>:45:1: error: • No instance for (Show GHC.Types.Any) arising from a use of ‘show’ And that's the second thing i don't understand: why it does not work, when i explicitly define type to be equal to GHC.Types.Any? Thanks. PS. I've read "Any types" notes in GHC.Builtin.Types, but apart from that ghc uses 'GHC.Types.Any' internally to unify (?) unconstrained types, i don't understand much, sorry.
On Jan 18, 2022, at 8:10 AM, Dmitriy Matrosov
wrote: On 1/17/22 6:49 PM, Dmitriy Matrosov wrote:
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce import qualified GHC.Types as GHC.Types
class FromTypeMaybe k where type ToType k fromTypeMaybe :: (a -> ToType k) -> Proxy k -> a -> Maybe (ToType k) instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where --type ToType 'Nothing = GHC.Types.Any type ToType 'Nothing = t fromTypeMaybe f _ x = Nothing instance forall (t :: Type). FromTypeMaybe ('Just @Type t) where type ToType ('Just t) = t fromTypeMaybe f _ x = Just (f x) then i've written a little more: type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail:: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
insertAny :: t -> [AnyData] -> [AnyData] insertAny x zs = AnyData x : zs
headAny :: forall ts . FromTypeMaybe (MaybeHead ts) => Proxy ts -> [AnyData] -> Maybe (ToType (MaybeHead ts)) headAny _ [] = Nothing headAny _ (x : xs) = fromTypeMaybe unAny (Proxy @(MaybeHead ts)) x And now it works, when type-level list is explicitly specified, like: *Main> headAny (Proxy @'[]) $ insertAny 1 $ insertAny True [] Nothing *Main> headAny (Proxy @'[Int]) $ insertAny 1 $ insertAny True [] Just 1 *Main> headAny (Proxy @'[Int, Bool]) $ insertAny 1 $ insertAny True [] Just 1 but if i use 'Tail' type-function first, it works only in two cases: for list with 2 or more elements *Main> :t headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] :: Maybe Int *Main> headAny (Proxy @(Tail '[Bool, Int])) $ insertAny 1 $ insertAny True [] Just 1 and empty list *Main> :t headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] :: Maybe t *Main> headAny (Proxy @(Tail '[])) $ insertAny 1 $ insertAny True [] Nothing But for list with 1 element it does not work *Main> :t headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] :: Maybe * *Main> headAny (Proxy @(Tail '[Bool])) $ insertAny 1 $ insertAny True [] <interactive>:246:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it ..... And besides i don't see any way of fixing my (FromTypeMaybe 'Nothing) instance.
I think, i've fixed everything. Eventually, it was very simple.
{-# LANGUAGE DataKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}
import Data.Kind import Data.Proxy import Unsafe.Coerce
class FromTypeMaybe2 k t where fromTypeMaybe2 :: (a -> t) -> Proxy k -> a -> Maybe t
instance FromTypeMaybe2 'Nothing t where fromTypeMaybe2 f _ _ = Nothing
instance (t ~ t') => FromTypeMaybe2 ('Just t) t' where fromTypeMaybe2 f _ x = Just (f x)
headAny2 :: forall t ts . FromTypeMaybe2 (MaybeHead ts) t => Proxy ts -> [AnyData] -> Maybe t headAny2 _ [] = Nothing headAny2 _ (x : xs) = fromTypeMaybe2 unAny (Proxy @(MaybeHead ts)) x
type MaybeHead :: [t] -> Maybe t type family MaybeHead ts where MaybeHead '[] = 'Nothing MaybeHead (x ': xs) = 'Just x
type Tail:: [t] -> [t] type family Tail ts where Tail '[] = '[] Tail (x ': xs) = xs
data AnyData where AnyData :: a -> AnyData
unAny :: AnyData -> t unAny (AnyData x) = unsafeCoerce x
And now everything works:
*Main> headAny2 (Proxy @'[]) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @'[Int]) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @'[Int, Bool]) $ [AnyData 1, AnyData True] Just 1
and
*Main> headAny2 (Proxy @(Tail '[Bool, Int])) $ [AnyData 1, AnyData True] Just 1 *Main> headAny2 (Proxy @(Tail '[Bool])) $ [AnyData 1, AnyData True] Nothing *Main> headAny2 (Proxy @(Tail '[])) $ [AnyData 1, AnyData True] Nothing
The only question, that remains is why defining 'Nothing resulting type to be 'GHC.Types.Any' in previous implementation
instance forall (t :: Type). FromTypeMaybe ('Nothing @t) where type ToType 'Nothing = GHC.Types.Any
does not fix it? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Thanks. Now I understand much better.
On Jan 27, 2022, at 10:25 AM, Dmitriy Matrosov
wrote: but when i use 'Tail' function on type-level list with 1 element, it does not work:
*Main> headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True]
<interactive>:22:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it
This is all about defaulting. The key question: what is the type of the expression you are typing? - With `headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True]`, the type is `Maybe (ToType (MaybeHead (Tail '[Bool])))`. We see that `Tail '[Bool] :: [Type]` reduces to `'[] :: [Type]`. Then, `MaybeHead (Tail '[Bool]) :: Maybe Type` reduces to `Nothing :: Maybe Type`. And finally `ToType (Nothing :: Maybe Type)` reduces to `Type`, meaning that your expression has type `Maybe Type`. Because GHC won't print out something unless it has a Show instance, it bleats, saying there is no Show instance for `Maybe Type`. - Now, consider `headAny @(Tail '[]) Proxy [AnyData 1, AnyData True]`. The result type is `Maybe (ToType (MaybeHead (Tail '[])))`. The point of interest here is: what is the type of `Tail '[]`? It's a list, but the element type is unconstrained. So GHC invents a fresh variable `t`. Following a similar sequence as above, we end up with assigning the expression the type `Maybe t`. At this point, GHC wants to print something of type `Maybe t` but doesn't know what `t` is. It tries `()` as a substitution for `t`. (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html?hi...) That works, and the "Nothing" is printed. In other circumstances -- where there is no Show constraint around, for example -- GHC will take an unknown type variable (like t) and default it to GHC.Types.Any. So, you're right that there is no `Show Any` constraint, but GHC doesn't need one, because of its clever (and confusing!) approach to defaulting. Does this help? Richard

On 1/28/22 11:48 PM, Richard Eisenberg wrote:
On Jan 27, 2022, at 10:25 AM, Dmitriy Matrosov
wrote: but when i use 'Tail' function on type-level list with 1 element, it does not work:
*Main> headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True]
<interactive>:22:1: error: • No instance for (Show *) arising from a use of ‘print’ • In a stmt of an interactive GHCi command: print it
This is all about defaulting.
The key question: what is the type of the expression you are typing?
- With `headAny @(Tail '[Bool]) Proxy [AnyData 1, AnyData True]`, the type is `Maybe (ToType (MaybeHead (Tail '[Bool])))`. We see that `Tail '[Bool] :: [Type]` reduces to `'[] :: [Type]`. Then, `MaybeHead (Tail '[Bool]) :: Maybe Type` reduces to `Nothing :: Maybe Type`. And finally `ToType (Nothing :: Maybe Type)` reduces to `Type`, meaning that your expression has type `Maybe Type`. Because GHC won't print out something unless it has a Show instance, it bleats, saying there is no Show instance for `Maybe Type`.
- Now, consider `headAny @(Tail '[]) Proxy [AnyData 1, AnyData True]`. The result type is `Maybe (ToType (MaybeHead (Tail '[])))`. The point of interest here is: what is the type of `Tail '[]`? It's a list, but the element type is unconstrained. So GHC invents a fresh variable `t`. Following a similar sequence as above, we end up with assigning the expression the type `Maybe t`. At this point, GHC wants to print something of type `Maybe t` but doesn't know what `t` is. It tries `()` as a substitution for `t`. (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html?hi...) That works, and the "Nothing" is printed.
In other circumstances -- where there is no Show constraint around, for example -- GHC will take an unknown type variable (like t) and default it to GHC.Types.Any. So, you're right that there is no `Show Any` constraint, but GHC doesn't need one, because of its clever (and confusing!) approach to defaulting.
Does this help? Richard
Yes, thanks! I understand now.
participants (3)
-
Dmitriy Matrosov
-
Richard Eisenberg
-
Viktor Dukhovni