Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯克尔:懒惰的评估能帮助提前停止投票吗?_Haskell_Lazy Evaluation - Fatal编程技术网

Haskell 哈斯克尔:懒惰的评估能帮助提前停止投票吗?

Haskell 哈斯克尔:懒惰的评估能帮助提前停止投票吗?,haskell,lazy-evaluation,Haskell,Lazy Evaluation,假设我有10个不同的函数(并行或非并行)决定同一个问题。 有没有一个好方法可以实现一个投票方案,当达到多数时,lazy会自动实现,而不需要更多的计算 obs:这更多的是关于懒惰ev的范围/限制的问题。 当然,一个简单的“如果”就可以检测出多数 谢谢 [编辑1] 。。。简单的“如果”可以检测到多数 对不起,我的意思是“单一如果”->“单一等待所有进程完成” 。。。平行与否 我只是不知道并行性在这种情况下很重要。如果我认为这些函数产生布尔值,问题就变成了,如果写出一个函数,它需要10个布尔值,如果6

假设我有10个不同的函数(并行或非并行)决定同一个问题。 有没有一个好方法可以实现一个投票方案,当达到多数时,lazy会自动实现,而不需要更多的计算

obs:这更多的是关于懒惰ev的范围/限制的问题。 当然,一个简单的“如果”就可以检测出多数

谢谢

[编辑1]

。。。简单的“如果”可以检测到多数

对不起,我的意思是“单一如果”->“单一等待所有进程完成”

。。。平行与否


我只是不知道并行性在这种情况下很重要。如果我认为这些函数产生布尔值,问题就变成了,如果写出一个函数,它需要10个布尔值,如果6个是真的,则总是返回真值,它总是需要小于其输入的10的值。p>
一种简单但不符合规定要求的方法是,依次测试每个输入,如果trues>=6停止返回true,则计数trues和false的数量;如果false>=6停止返回false,则计数trues和false的数量;如果我们到达最后一个输入时未触发任何一个条件,则返回false。由于这将在某些情况下测试所有输入,因此我认为这个问题的答案是否定的,在本例中,延迟求值没有帮助。

您想要这样的函数:

majority :: [Bool] -> Bool
voteByTrue list = sum (map bToNat list) >= threshold
  where
    threshold = (genericLength list + 1) `quot` 2
你想让它并行工作。举手之劳不幸的是,我不知道一种不绕过类型系统的方法。下面是一个示例实现:

import Control.Concurrent
import Control.Concurrent.MVar
import System.IO.Unsafe

majority :: [Bool] -> Bool
majority votes = unsafePerformIO $
  do v <- newEmptyMVar
     nfalse <- newMVar 0
     ntrue <- newMVar 0
     let n = length votes
         m = (n `div` 2) + 1
         count x =
           let (var, min) = if x then (ntrue, m) else (nfalse, n-m+1)
           in do i <- modifyMVar var $ \i -> return (i+1, i+1)
                 if i == min then putMVar v x else return ()
     threads <- mapM (forkIO . count) votes
     r <- takeMVar v
     mapM_ killThread threads
     return r
导入控制。并发
导入控制.Concurrent.MVar
导入System.IO不安全
多数::[Bool]->Bool
多数票=不安全$

做一个简短的回答。是的,实施这样一个系统是可能的,但是不,内在的懒惰对你没有帮助

答案很长。我认为你需要一点不同的懒惰。Haskell的惰性评估是一种,其工作原理如下:

  • 调用该函数时,evaluator尝试首先计算它,而不计算其参数
  • 如果控制流到达需要计算某个参数的点,它将对其求值。然后继续对函数进行评估 因此,参数会根据需要“按需”进行评估。并对其逐一进行了评价。对于语言本身来说,这是一个好主意,即使是具有应用程序求值顺序的命令式语言,如果没有这样的惰性函数也无法工作-在大多数编程语言中,像
    这样的操作符本质上是惰性的。但在你的情况下,这是你真正需要的吗?不。您需要并行计算所有参数,并在计算某些参数时完成函数本身的计算

    如何实现。您需要完全重新实现评估系统,我相信没有副作用的纯函数式编程和懒惰的评估只会阻碍您。这里有一个方法。创建函数,例如,
    paply::[ArgumentType]->TriggerFunction->ResultType
    ,其中
    pappy
    代表“并行应用”,
    ArgumentType
    是要计算的实际参数类型(在您的情况下可能是函数的闭包+要解决的问题),
    TriggerFunction
    是一个函数,在计算其中一个参数时调用,并且在您的示例中,
    ResultType
    是布尔值。此功能必须按如下方式工作:

  • 并行运行所有参数的计算
  • 当计算其中一个参数时,它必须使用计算结果调用Trigger函数
  • 触发器函数必须有一个“内存”来记住所有以前的结果。如果在调用时,它发现有足够的参数来完成对主函数的求值,它就会这样做,从而中断对其余参数的计算
    这只是其中一种方法,不是最实用的(它使用可变的“内存”)。您还可以与其他参数并行运行触发器函数,并使用某种同步在所有参数之间传递控制。或者您可以使用诸如Erlang或Scala中的某种消息。不幸的是,我没有足够的Haskell经验来编写实际的代码,但是@Dietrich Epp的帖子似乎代表了类似的想法,所以您可以将其作为基础

    您可以使用懒惰的自然语言来完成这项工作,而无需进行简单的并行计算。在本例中,我选择在hackage上使用peano inf包:

    请注意,5不会打印在跟踪中,因为在此之前会缩短评估

    要使用并行性实现这一点,需要手动生成和终止线程等,这很好,但肯定不那么令人愉快


    请注意,上述代码使用标准和。这种不常见的用例就是为什么,尽管很多人觉得它不值得,但sum没有尽可能严格。

    我尝试将sclv的解决方案与luqui关于
    unab
    的评论结合起来,并想分享我的结果。我将从测试用例开始:

    list1 = [True, True, undefined, True, undefined]
    list2 = [undefined, False, False]
    list3 = concat $ replicate 500 list1
    list4 = concat $ replicate 500 list2
    
    
    main = mapM (print . vote) [list1, list2, list3, list4]
    
    vote :: [Bool] -> Bool
    
    这应该打印出来

    True
    False
    True
    False
    
    我首先从
    list1
    示例开始。通过它的投票函数可以如下所示:

    majority :: [Bool] -> Bool
    
    voteByTrue list = sum (map bToNat list) >= threshold
      where
        threshold = (genericLength list + 1) `quot` 2
    
    这与sclv的答案相同。现在我们需要使
    sum
    更延迟,以便在遇到
    未定义的
    summand时计算不会中止。我的第一个想法是:

    Zero |+ y = y
    Succ x |+ y = Succ (x + y)
    
    instance Num Nat where
        x + y = (x |+ y) `lub` (y |+ x)
    
    这里,
    |+
    在其第一个参数中是严格的加法运算符,
    +
    在其两个参数中都是非严格的。它适用于玩具示例,如
    list1
    ,但由于线程数呈指数级增长,该解决方案的性能会迅速恶化(请参见每个
    +
    如何生成2个线程,每个线程通常使用相同的参数再次调用
    +
    )。有了这样的表现,
    投票列表3
    的终止速度不够快。为了对抗这一点,我
    instance Num Nat where
        x + y = x' |+ y' where (y', x') = infoMinMax x y
    
    vote list = voteByTrue list `maxInfo` voteByFalse list
      where
        voteByFalse = not . voteByTrue . map not
        maxInfo x y = snd (infoMinMax x y)