Ограничение конструкторов в сигнатуре

Итак, я работаю над забавным экспериментом в контекстном смысле, и я натыкаюсь на стену. Я пытаюсь определить тип данных, который может быть либо примитивом, либо функцией, которая преобразуется из одного конструктора в другой.

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)

Проблема в том, что сигнатура для ofTheAbyssдопускает любую часть оружия в качестве аргумента, тогда как я хочу разрешить только аргументы, созданные WTrans. Вы можете видеть, что я написал только совпадение с образцом для этого случая.

Я пытался использовать GADT, но боюсь, что это была кроличья нора. Никогда не мог заставить их делать то, что я хотел. Есть ли у кого-нибудь идеи, как я могу использовать только аргументы WTrans в ofTheAbyss? Или я просто что-то совсем упускаю.

Спасибо.

Лучший, Эрик

5
задан Erik Hinton 27 May 2012 в 06:37
поделиться