簡體   English   中英

Haskell剛性類型變量錯誤

[英]Haskell rigid type variable error

我是Haskell初學者。 我想知道以下原因為何不起作用:

import System.Random

simulator :: (RandomGen g) => g -> Double -> (Bool, g)
simulator gen p = (x <= p, gen2)
    where (x, gen2) = random gen :: (Double, g)

我得到的錯誤是:

• Couldn't match type ‘g’ with ‘g1’
  ‘g’ is a rigid type variable bound by
    the type signature for:
      simulator :: forall g. RandomGen g => g -> Double -> (Bool, g)
    at simulate.hs:10:1-54
  ‘g1’ is a rigid type variable bound by
    an expression type signature:
      forall g1. (Double, g1)
    at simulate.hs:12:37-47
  Expected type: (Double, g1)
    Actual type: (Double, g)
• In the expression: random gen :: (Double, g)
  In a pattern binding: (x, gen2) = random gen :: (Double, g)
  In an equation for ‘simulator’:
      simulator gen p
        = (x <= p, gen2)
        where
            (x, gen2) = random gen :: (Double, g)
• Relevant bindings include
    gen :: g (bound at simulate.hs:11:11)
    simulator :: g -> Double -> (Bool, g) (bound at simulate.hs:11:1)

     where (x, gen2) = random gen :: (Double, g)

似乎Haskell無法匹配類型變量g的單獨實例。 有什么線索嗎?

代碼的問題在最后一行,即帶有:: (Double, g)類型注釋的代碼。 如所寫,您顯然希望該批注中的g指向與您simulator類型簽名中的g相同的g 這是一個完全合理的期望,但是不幸的是,事實並非如此-默認情況下,兩個名稱相同的類型變量在不同的類型注釋中是不同的。 (這就是為什么在錯誤消息中,GHC將第二個g隱式重命名為g1 。)

幸運的是,您可以解決此問題。 GHC帶有您可以打開的語言擴展,稱為ScopedTypeVariables 如果將{-# LANGUAGE ScopedTypeVariables #-}到模塊頂部,則會啟用擴展。 但是,這仍然不能解決您的程序,因為ScopedTypeVariables僅適用於使用forall 明確綁定的變量。 因此,你需要在兩個添加LANGUAGE編譯引入明確使用forall

{-# LANGUAGE ScopedTypeVariables #-}

import System.Random

simulator :: forall g. (RandomGen g) => g -> Double -> (Bool, g)
simulator gen p = (x <= p, gen2)
  where (x, gen2) = random gen :: (Double, g)

這些咒語足以使GHC達到您最初的意圖。

就是說,如果您只是刪除第二個類型簽名並禁用ScopedTypeVariables ,則原始程序實際上也將編譯,因為GHC會根據使用方式為gen2推斷合適的類型。 是否需要類型簽名是個人喜好,但是對於您確定確實需要簽名的情況或實際需要簽名的情況,了解發生的情況以及如何解決它仍然很有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM