【问题标题】:Haskell: Order-Insensitive Functional ApplicationHaskell:顺序不敏感的函数式应用程序
【发布时间】:2012-04-24 17:33:17
【问题描述】:

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

tl = [1..10]

bill :: Int
bill = 1

tall :: Int -> Bool
tall = \x -> x `elem` tl

将句子“Bill is high”想象成一棵树,左叶被“Bill”占据,右叶被“tall”占据。我们通过将 right 叶的 sv 应用到 left 叶的 sv 来计算句子的真值。现在考虑'Some man is high':这里左叶被'some man'占据[其sv的类型为:: (Int -> Bool) -> Bool],右叶被'tall'占据[其 sv 的类型为 :: (Int -> Bool)]。我们通过将 left 叶的 sv 应用到 right 叶的 sv 来计算句子的真值。

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

我将如何在 Haskell 中实现这种“顺序不敏感”的功能应用程序?我编写了一些函数,通过解析

的结果来确定哪个叶子在另一个的域中
show (typeOf a)

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

bill tall

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

【问题讨论】:

    标签: haskell exception-handling functional-programming


    【解决方案1】:

    您无法在运行时捕获类型不匹配;这是一个编译时错误。 (至少,不是不使用 ghc-api 在运行时编译代码。ghci 是 ghc-api 的包装器,这就是它可以做到这一点的原因。)您需要找到一种方法来捕获这种类型的区别ADT 在运行时执行此操作,或者可能使用类型类(但这会带来其他复杂性)。

    【讨论】:

      【解决方案2】:

      你可能会通过一些类型类扩展获得很长的路要走:

      {-# 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
      

      【讨论】:

      • 谢谢,这很有帮助!我想我会遵循这个策略。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多