[英]Extending GADTs examples - could not deduce
我正在尝试围绕评估Value
扩展经典的 GADT 示例,但我遇到了一些我不完全理解的东西。
data Command a where
Base64_ :: Command a
Take_ :: Int -> Command a
-- eval only works with this definition
-- with this uncommented, cmd breaks with:
--
-- Could not deduce: v ~ T.Text
-- from the context: a ~ T.Text
-- bound by a pattern with constructor:
-- VString :: T.Text -> Value T.Text,
-- in an equation for ‘cmd’
-- ‘v’ is a rigid type variable bound by
-- the type signature for:
-- cmd :: forall c a v. Command c -> Value a -> Value v
data Value v where
VString :: T.Text -> Value T.Text
VInt :: Int -> Value Int
VBool :: Bool -> Value Bool
VNot :: Value Bool -> Value Bool
-- cmd only works with this definition
-- with this uncommented, eval breaks with:
--
-- Couldn't match expected type ‘a’ with actual type ‘T.Text’
-- ‘a’ is a rigid type variable bound by
-- the type signature for:
-- eval :: forall a. Value a -> a
-- data Value v where
-- VString :: T.Text -> Value v
-- VInt :: Int -> Value v
-- VBool :: Bool -> Value v
-- VNot :: Value Bool -> Value v
eval :: Value a -> a
eval (VString i) = i
eval (VInt i) = i
eval (VBool b) = b
eval (VNot b) = not $ eval b
cmd :: Command c -> Value a -> Value v
cmd Base64_ (VString s) = VString $ encodeBase64 s
cmd (_) (_) = VInt 3 -- or show error for no match.
我正在尝试做的事情可能吗? 是否有一个 GADT 定义可以同时与eval
和cmd
,还是我得到的 function 签名之一不正确?
类型签名:
cmd :: Command c -> Value a -> Value v
表示任何“类型” c
的Command c
采用任何“类型” a
的Value a
,并且可以产生任何调用者请求的“类型” v
Value v
但是,您的Base64_
命令不采用任何类型的Value a
,它只采用Value T.Text
,并且它不产生调用者想要的任何类型的Value v
,它只产生一个Value T.Text
。
您可能想要做的是构建您的Command c
GADT 以便c
部分确定允许的输入a
和实际 output v
。
一种方法是使用具有多种类型 arguments 的 GADT,例如:
data Command a v where
Base64_ :: Command T.Text T.Text
IsZero_ :: Command Int Bool
其中a
表示输入类型, v
表示每个定义命令的 output 类型。
现在,签名:
cmd :: Command a v -> Value a -> Value v
表达了这样的想法,即对于a
和v
的具体值的特定类型的Command av
可以预期接受Value a
并产生Value v
,并且以下定义将起作用:
cmd :: Command a v -> Value a -> Value v
cmd Base64_ (VString s) = VString $ encodeBase64 s
cmd IsZero_ (VInt x) = VBool $ x == 0
完整示例:
{-# LANGUAGE GADTs #-}
import qualified Data.Text as T
import Data.Text.Encoding.Base64
data Command a v where
Base64_ :: Command T.Text T.Text
IsZero_ :: Command Int Bool
data Value v where
VString :: T.Text -> Value T.Text
VInt :: Int -> Value Int
VBool :: Bool -> Value Bool
VNot :: Value Bool -> Value Bool
eval :: Value a -> a
eval (VString i) = i
eval (VInt i) = i
eval (VBool b) = b
eval (VNot b) = not $ eval b
cmd :: Command a v -> Value a -> Value v
cmd Base64_ (VString s) = VString $ encodeBase64 s
cmd IsZero_ (VInt x) = VBool $ x == 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.