Haskell:顺序不敏感的功能应用

EB *_*udd 4 haskell functional-programming exception-handling

我想在Haskell中实现一个对顺序不敏感的功能应用程序版本.通过一点背景:自然语言语义的一个突出传统(源自Richard Montague等)将各种类型的lambda函数指定为表达式的语义值(sv).句子的真值是通过对句子成分的sv进行功能性应用来计算的.举个简单的例子,考虑一下:

tl = [1..10]

bill :: Int
bill = 1

tall :: Int -> Bool
tall = \x -> x `elem` tl
Run Code Online (Sandbox Code Playgroud)

把"比尔很高"的句子想象成一棵树,左边的叶子被'比尔'占据,而右边的叶子被'高'占据.我们通过将叶的sv应用于叶的sv来计算句子的真值.现在考虑'有些男人很高':这里左边的叶子被"某个男人"占据[其中sv的类型为::(Int - > Bool) - > Bool]而右边的叶子被"高个子"占据[其sv的类型为::(Int - > Bool)].我们通过应用的SV计算句子的真值叶到的SV 叶.

因此,在这个系统中,给定一个左叶a和右叶b的树,我们首先检查哪个叶在另一个叶的域中,然后相应地应用功能应用:如果ab的域中,我们做b (a),如果ba的范围内,我们做(b).

我如何在Haskell中实现这种"顺序不敏感"的功能应用程序?我编写了一些函数,通过解析结果来确定哪个叶子在另一个域中

show (typeOf a)
Run Code Online (Sandbox Code Playgroud)

一片叶子 然而,这在我看来是不必要的麻烦.如果您尝试评估,Ghci会出错

bill tall
Run Code Online (Sandbox Code Playgroud)

因此,检查哪个项目在另一个域中的简单方法是尝试将一个项目应用于另一个项目,并查看是否出现错误/异常.那么我的问题是:如何捕获由类型不匹配导致的异常?也就是说,如何捕获此类非IO异常?

gee*_*aur 7

您无法在运行时捕获类型不匹配; 这是一个编译时错误.(至少,并非没有使用ghc-api在运行时编译代码. ghci是ghc-api的包装,这就是为什么它可以做到这一点.)你需要找到一种方法来捕获ADT中的这种类型区别来做它在运行时,或者可能使用类型类(这引入了其他复杂性).


Ste*_*ans 6

对于某些类类扩展,您可能会有很长的路要走:

{-# 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 ($)   
Run Code Online (Sandbox Code Playgroud)

例如,如果我们现在定义

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]
Run Code Online (Sandbox Code Playgroud)

我们得到

> bill `is` tall
True

> someMan `is` tall
True

> allMan `is` tall
False
Run Code Online (Sandbox Code Playgroud)

直截了当,有

are :: Copula l r => l -> r -> Sem l r
are = is
Run Code Online (Sandbox Code Playgroud)

我们可以做的

> someMan `are` tall
True

> allMan `are` tall
False
Run Code Online (Sandbox Code Playgroud)

这可能看起来更好一点.

注意:虽然这看起来很整洁,但一般来说,在多态上下文中,类型检查器需要一些帮助来确定要做什么.例如

> [] `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
Run Code Online (Sandbox Code Playgroud)

> ([] :: [Int]) `is` (null :: [Int] -> Bool)
True
Run Code Online (Sandbox Code Playgroud)