When you announce
leftthing :: a -> Leftthing a
you say that the caller leftthingchooses that a.
When you write
leftthing (Twothings a b) = leftthing a
You assume that you have selected a type Twothings, and, as it is not necessary, your program is rejected.
, , , Twothings, ! , .
. leftthing leftthing.
type family Leftthing a where
Leftthing (Twothings a b) = Leftthing{-you forgot the recursion!-} a
Leftthing a = a
GADT Twothing ness.
data IsItTwothings :: * -> * where
YesItIs :: IsItTwothings a -> IsItTwothings (Twothings a b)
NoItIsn't :: Leftthing a ~ a => IsItTwothings a
-- ^^^^^^^^^^^^^^^ this constraint will hold for any type
-- which is *definitely not* a Twothings type
:
leftthing :: IsItTwothings a -> a -> Leftthing a
leftthing (YesItIs r) (Twothings a b) = leftthing r a
leftthing NoItIsn't b = b
, - Twothings es . , .
> leftthing (YesItIs (YesItIs NoItIsn't)) (Twothings (Twothings True 11) (Twothings "strange" [42]))
True
, , . , ( , ). ( ). , .
, ,
leftthing :: pi a. a -> Leftthing a
pi - , , , . , , .