Signature constructor restriction

So, I'm working on an interesting experiment in contextual meaning, and I'm running into a wall. I am trying to determine a data type, which can be either primitive or a function that converts from one constructor to another.

data WeaponPart =
    WInt Int |
    WHash (Map.Map String Int) |
    WNull |
    WTrans (WeaponPart -> WeaponPart)

instance Show WeaponPart where
    show (WInt x) = "WInt " ++ (show x)
    show (WHash x) = "WHash " ++ (show x)
    show (WTrans _) = "WTrans"
    show WNull = "WNull"

cold :: WeaponPart -> WeaponPart
cold (WInt x) = WHash (Map.singleton "frost" x)
cold (WHash x) = WHash $ Map.insertWith (+) "frost" 5 x
cold (WTrans x) = cold $ x (WInt 5)
cold (WNull) = cold $ (WInt 5)

ofTheAbyss :: WeaponPart -> WeaponPart
ofTheAbyss (WTrans x) = x (WTrans x)

The problem is that the signature for ofTheAbyssallows any weapon as an argument, whereas I only want to allow WTrans constructors. You can see that I wrote only a template for this case.

I tried to do with GADT, but I'm afraid it was a rabbit hole. They could never make them do what I wanted. Does anyone have any ideas how I can only apply WTrans arguments in TheAbyss? Or I just completely missed something.

Thank.

Best, Erik

+5
source
3

GADT. , , , . PolyKinds, .

, , .

data Sort = Base | Compound

, . .

data WeaponPart :: Sort -> * where
  WInt    :: Int ->                                   WeaponPart Base
  WHash   :: Map.Map String Int ->                    WeaponPart Base
  WNull   ::                                          WeaponPart Base
  WTrans  :: (Some WeaponPart -> Some WeaponPart) ->  WeaponPart Compound

& lsquo; & rsquo; , :

data Some p where
  Wit :: p x -> Some p

, x , & lsquo; evidence & rsquo; x & lsquo; & rsquo; p. : Some data, newtype GHC newtype s.

Sort - . , , Some p -> ... forall x. p x -> ....

instance Show (WeaponPart x) where
  show (WInt x)    = "WInt " ++ (show x)
  show (WHash x)   = "WHash " ++ (show x)
  show (WTrans _)  = "WTrans"
  show WNull       = "WNull"

Sort - : .

cold :: Some WeaponPart -> Some WeaponPart
cold (Wit (WInt x))    = Wit (WHash (Map.singleton "frost" x))
cold (Wit (WHash x))   = Wit (WHash $ Map.insertWith (+) "frost" 5 x)
cold (Wit (WTrans x))  = cold $ x (Wit (WInt 5))
cold (Wit WNull)       = cold $ Wit (WInt 5)

Wit , .

ofTheAbyss :: WeaponPart Compound -> Some WeaponPart
ofTheAbyss (WTrans x) = x (Wit (WTrans x))

. : , , , - , . , .

+10

: . , , .

data WeaponPartBase
    = WInt Int
    | WHash (Map.Map String Int)
    | WNull

data WeaponPartCompound = WTrans (WeaponPart -> WeaponPart)
data WeaponPart = Base WeaponPartBase | Compound WeaponPartCompound

cold :: WeaponPart -> WeaponPart
cold (Base (WInt x)) = Base (WHash (Map.singleton "frost" x))
cold (Base (WHash x)) = Base (WHash $ Map.insertWith (+) "frost" 5 x)
cold (Base WNull) = cold (Base (WInt 5))
cold (Compound (WTrans x)) = cold (x (Base (WInt 5))

ofTheAbyss :: WeaponPartCompound -> WeaponPart
ofTheAbyss (WTrans x) = x (WCompound (WTrans x))

, :

class Basic a where
    wint :: Int -> a
    whash :: Map.Map String Int -> a
    wnull :: a

class Compounded a where
    wtrans :: (WeaponPart -> WeaponPart) -> a

instance Basic WeaponPartBase where
    wint = WInt
    whash = WHash
    wnull = WNull

instance Basic WeaponPart where
    wint = Base . wint
    whash = Base . whash
    wnull = Base wnull

instance Compounded WeaponPartCompound where
    wtrans = WTrans

instance Compounded WeaponPartCompound where
    wtrans = Compound . wtrans

, , cold ofTheAbyss :

cold' (Base (WInt x)) = whash (Map.singleton "frost" x)
cold' (Base (WHash x)) = whash $ Map.insertWith (+) "frost" 5 x
cold' (Base WNull) = cold' (wint 5)
cold' (Compound (WTrans x)) = cold' (x (wint 5))

ofTheAbyss' (WTrans x) = x (wtrans x)
+3

, . .

, - , WeaponPart, ofTheAbyss , typecheck .

:

a) Give the ofTheAbysstype (WeaponPart -> WeaponPart) -> WeaponPartby "unpacking" the constructor.

b) Give a ofTheAbyssruntime error in all other constructors.

 ofTheAbyss :: WeaponPart -> WeaponPart
 ofTheAbyss (WTrans x) = x (WTrans x)
 ofTheAbyss _ = error "Illegal argument to ofTheAbyss was not a WTrans"
+1
source

All Articles