Haskell-帮助使用高级类型功能简化函数

Haskell-帮助使用高级类型功能简化函数,haskell,interpreter,dynamic-typing,Haskell,Interpreter,Dynamic Typing,我正在用Haskell为一种动态类型语言编写一个解释器 和大多数动态类型语言解释器一样,我的程序也需要在运行时检查类型。我的程序中最常用的代码之一是: interpreterFunction :: Value -> SomeMonadicContext ReturnType interpreterFunction p = do VStr s <- ensureType p TString .. some code that uses s 所以我根据它们的类型

我正在用Haskell为一种动态类型语言编写一个解释器

和大多数动态类型语言解释器一样,我的程序也需要在运行时检查类型。我的程序中最常用的代码之一是:

interpreterFunction :: Value -> SomeMonadicContext ReturnType
interpreterFunction p = do
    VStr s <- ensureType p TString
    ..
    some code that uses s
所以我根据它们的类型来划分我的值。即,我只有一个值构造函数的类型为
TStr

现在我想知道是否有办法简化我的
ensureType
函数和解构代码。例如,这样的事情可能发生吗:

interpreterFunction p = do
    s <- ensureType p
    ..
    same code that uses s
解释器函数p=do

s是的,事实上,您可以在类型类的帮助下做到这一点。它是否合理值得商榷(对于简单的
类型,模式匹配可能是更好的解决方案),但它仍然很有趣:)

当无法推断特定类型时,还可以使用
ScopedTypeVariables
扩展强制该类型:

{-# LANGUAGE ScopedTypeVariables #-}
interpreterFunction2 :: Value -> IO ()
interpreterFunction2 val = 
    do (s :: String) <- ensureType val
       print s
1.干净、清晰、简单的方式: 我认为您定义的标记联合类型

data Value = VStr String | VInt Int | VBool Bool
将您需要的所有运行时类型检查都内置为普通的旧模式匹配,而将其包装在某些高级类型系统功能中缺少一个干净清晰的解决方案:

interpreterFunction :: Value -> SomeMonadicContext ReturnType
interpreterFunction (Vstr s) = do
    some code that uses s
interpreterFunction _ = do
    some error handling code
你喜欢:

interpreterFunction p = do
    s <- ensureType p
    ..
    same code that uses s
示例:

instance FromValue String where
   ensureType (VStr s) = return s
   ensureType  _       = fail $ unlines 
                          ["Yikes, I'd rather have thrown a Nothing than a fail,"
                          ,"but then I'd have to have detagged the Just later"
                          ,"and then I may as well have used solution 1 anyway!"]

instance FromValue Int where
   ensureType (VInt i) = return i
   ensureType  _       = fail "Oh no, do I really have to use catch?"
这会给

interpreterFunction :: Value -> IO String
interpreterFunction p = do
    s <- ensureType p
    return $ s ++ ", yay!" -- example String-specific code.
解释器函数::值->IO字符串
解释器功能p=do

s它可能有助于描述在存在非字符串数据的情况下
ensureType
的效果。目前,您似乎可以使用模式匹配将其重写为
interprecrfunction(VStr s)=一些使用s
的代码,后跟
interprecrfunction
。否则,我认为您应该仔细研究一下,因为它们可能会对您的代码产生澄清作用。您所要求的是有意义的,而且听起来像是您所要求的(尽管不一定是唯一或最好的解决方案)。它们允许您定义“类型函数”(例如从
String
VStr
,其中
VStr
是一种新类型),它可以是内射的,也可以不是内射的。@AndrewC,简单的模式匹配对我不起作用,因为我在问题中没有提到一些细节。基本上,我还想从it中找到
投手或$TypeError,并做一些其他事情。@jberryman有人能给我一些关于TypeFamilies如何帮助的建议吗?太好了,这个解决方案对我很有用,也很简单。非常感谢你的回答。也许我应该在这里补充一两句关于为什么模式匹配不能解决我的问题的话,但我只是想让问题简短一些。@sinan啊-也许在要求回答您问题下的评论之后,再继续刷新页面一段时间是个好主意,这样您就可以得到更多定制的答案。我现在没有时间给你们一个答案,但这很有趣。也许你可以在问题的底部加上“编辑:我也对是否有一个类型族解决方案感兴趣”,以防引起其他人的兴趣。Pob hwyl。
data Value = VStr String | VInt Int | VBool Bool
interpreterFunction :: Value -> SomeMonadicContext ReturnType
interpreterFunction (Vstr s) = do
    some code that uses s
interpreterFunction _ = do
    some error handling code
interpreterFunction p = do
    s <- ensureType p
    ..
    same code that uses s
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

class FromValue a where 
   ensureType :: Value -> SomeMonadicContext a
instance FromValue String where
   ensureType (VStr s) = return s
   ensureType  _       = fail $ unlines 
                          ["Yikes, I'd rather have thrown a Nothing than a fail,"
                          ,"but then I'd have to have detagged the Just later"
                          ,"and then I may as well have used solution 1 anyway!"]

instance FromValue Int where
   ensureType (VInt i) = return i
   ensureType  _       = fail "Oh no, do I really have to use catch?"
interpreterFunction :: Value -> IO String
interpreterFunction p = do
    s <- ensureType p
    return $ s ++ ", yay!" -- example String-specific code.