Haskell:顺序不敏感的函数应用程序
我想在Haskell中实现一个不区分顺序的函数应用程序版本。作为一个小背景:自然语言语义学的一个突出传统(源自Richard Montague等)将各种类型的lambda函数指定为表达式的语义值(sv)。句子的真值是通过对句子成分的sv进行功能应用来计算的。举个简单的例子,请考虑:Haskell:顺序不敏感的函数应用程序,haskell,exception-handling,functional-programming,Haskell,Exception Handling,Functional Programming,我想在Haskell中实现一个不区分顺序的函数应用程序版本。作为一个小背景:自然语言语义学的一个突出传统(源自Richard Montague等)将各种类型的lambda函数指定为表达式的语义值(sv)。句子的真值是通过对句子成分的sv进行功能应用来计算的。举个简单的例子,请考虑: tl = [1..10] bill :: Int bill = 1 tall :: Int -> Bool tall = \x -> x `elem` tl 把“比尔是高的”这句话想象成一棵树,左叶
tl = [1..10]
bill :: Int
bill = 1
tall :: Int -> Bool
tall = \x -> x `elem` tl
把“比尔是高的”这句话想象成一棵树,左叶被“比尔”占据,右叶被“高的”占据。我们通过将右叶的sv应用于左叶的sv来计算句子的真值。现在考虑一下“一个人是高的”:这里左边的叶子被‘某个人’占据[它的SV类型::(int -BoOL)->布尔],右边的叶子被‘高’占据[它的SV类型::(int -BoOL)]。我们通过将左叶的sv应用于右叶的sv来计算句子的真值
因此,在这个系统中,给定一棵具有左叶a和右叶b的树,我们首先检查哪个叶在另一个叶的域中,然后相应地应用函数应用程序:如果a在b的域中,我们做b(a),而如果b在a的域中,我们做a(b)
我如何在Haskell中实现这种“顺序不敏感”的功能性应用程序?我编写了一些函数,通过解析
show (typeOf a)
为了一片叶子。然而,在我看来,这似乎是不必要的麻烦。如果您尝试(例如)评估,Ghci会给出一个错误
bill tall
因此,检查哪个项目在另一个项目的域中的一个简单方法就是尝试将一个项目应用到另一个项目,并查看是否会导致错误/异常。那么,我的问题是:如何捕获由类型不匹配导致的异常?也就是说,如何捕获此类非IO异常?您无法在运行时捕获类型不匹配;这是一个编译时错误。(至少,如果不在运行时使用ghc api编译代码,
ghci
是ghc api的包装器,这就是为什么它可以做到这一点。)您需要找到一种方法在ADT中捕获这种类型差异,以便在运行时执行此操作,或者可能使用一个typeclass(不过这会带来其他复杂性).对于某些类型类扩展,您可能会有很长的路要走:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
class Copula l r where
type Sem l r :: *
is :: l -> r -> Sem l r
instance Copula (a -> b) a where
type Sem (a -> b) a = b
is = ($)
instance Copula a (a -> b) where
type Sem a (a -> b) = b
is = flip ($)
例如,如果我们现在定义
bill :: Int
bill = 1
tall :: Int -> Bool
tall = \x -> x `elem` tl
someMan :: (Int -> Bool) -> Bool
someMan = flip any [1 .. 20]
allMan :: (Int -> Bool) -> Bool
allMan = flip all [1 .. 20]
我们得到
> bill `is` tall
True
> someMan `is` tall
True
> allMan `is` tall
False
直截了当地
are :: Copula l r => l -> r -> Sem l r
are = is
我们能做到
> someMan `are` tall
True
> allMan `are` tall
False
看起来可能会好一点
注意:虽然这看起来很简洁,但一般来说,在多态上下文中,类型检查器需要相当多的帮助来确定要做什么。比如说
> [] `is` null
<interactive>:37:4:
No instance for (Copula [a0] ([a1] -> Bool))
arising from a use of `is'
Possible fix:
add an instance declaration for (Copula [a0] ([a1] -> Bool))
In the expression: [] `is` null
In an equation for `it': it = [] `is` null
谢谢,这很有帮助!我想我会采取这个策略。
> ([] :: [Int]) `is` (null :: [Int] -> Bool)
True