- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在处理 following book学习 Haskell - 特别关注 randomness 的章节:
我正在运行以下文件作为文件 three-coins.hs
:
import System.Random
threeCoins :: StdGen -> (Bool, Bool, Bool)
threeCoins gen =
let (firstCoin, newGen) = random gen
(secondCoin, newGen') = random newGen
(thirdCoin, newGen'') = random newGen'
in (firstCoin, secondCoin, thirdCoin)
main = print ( threeCoins (mkStdGen 21) )
runhaskell three-coins.hs
执行并获得类似于以下内容的输出:
(True,True,True)
Notice that we didn't have to do
random gen :: (Bool, StdGen)
. That's because we already specified that we want booleans in the type declaration of the function. That's why Haskell can infer that we want a boolean value in this case.
ghci
中运行它时使用以下代码:
import System.Random
:{
threeCoins :: StdGen -> (Bool, Bool, Bool)
threeCoins gen =
let (firstCoin, newGen) = random gen
(secondCoin, newGen') = random newGen
(thirdCoin, newGen'') = random newGen'
in (firstCoin, secondCoin, thirdCoin)
:}
<interactive>:6:9: error:
• Ambiguous type variable ‘t0’
prevents the constraint ‘(Random t0)’ from being solved.
• When checking that the inferred type
newGen :: forall t. Random t => StdGen
is as general as its inferred signature
newGen :: StdGen
In the expression:
let
(firstCoin, newGen) = random gen
(secondCoin, newGen') = random newGen
(thirdCoin, newGen'') = random newGen'
in (firstCoin, secondCoin, thirdCoin)
In an equation for ‘threeCoins’:
threeCoins gen
= let
(firstCoin, newGen) = random gen
(secondCoin, newGen') = random newGen
....
in (firstCoin, secondCoin, thirdCoin)
import System.Random
:{
threeCoins :: StdGen -> (Bool, Bool, Bool)
threeCoins gen =
let (firstCoin, newGen) = random gen :: (Bool, StdGen)
(secondCoin, newGen') = random newGen :: (Bool, StdGen)
(thirdCoin, newGen'') = random newGen' :: (Bool, StdGen)
in (firstCoin, secondCoin, thirdCoin)
:}
threeCoins (mkStdGen 21)
(True,True,True)
最佳答案
正如 chi 已经评论的那样,此代码仅在 monomorphism restriction 时有效。已启用。该限制使编译器为任何非函数定义选择一种特定类型,即其中没有类型变量的签名,如 a
在 length :: [a] -> Int
.因此(除非您手动指定了本地签名)编译器在选择之前到处寻找这种类型可能是什么的提示。在您的示例中,它看到 firstCoin
secondCoin
thirdCoin
用于最终结果,在顶层签名声明为 (Bool, Bool, Bool)
,因此它推断所有硬币必须具有类型Bool
.
在这样一个简单的例子中这很好,但在现代 Haskell 中,您经常需要更通用的值,因此您可以在多个不同类型的上下文中使用它们或作为 Rank-2 函数的参数。你总是可以通过给出明确的签名来实现这一点,但特别是在 GHCi 中这很尴尬(它通常被称为“可怕的单态限制”),因此几个版本之前决定在 GHCi 中默认禁用它。
从概念上讲,firstCoin
secondCoin
thirdCoin
等也可能比 Bool
更通用: random
毕竟能够产生任何合适类型的随机值(即任何具有 Random
实例的类型)。所以原则上,本地定义可以有一个多态类型,像这样:
threeCoins :: StdGen -> (Bool, Bool, Bool)
threeCoins gen =
let firstCoin, secondCoin, thirdCoin :: Random r => r
(firstCoin, newGen) = random gen
(secondCoin, newGen') = random newGen
(thirdCoin, newGen'') = random newGen'
in (firstCoin, secondCoin, thirdCoin)
{-# LANGUAGE NoMonomorphismRestriction #-}
r
的类型信息变量必须先传播回元组,然后才能在
random
中使用。生成器,由于我现在也不明白的原因,Hindley-Milner 类型系统无法做到这一点。
import System.Random
import Data.Random
threeCoins :: RVar (Bool, Bool, Bool)
threeCoins = do
firstCoin <- uniform False True
secondCoin <- uniform False True
thirdCoin <- uniform False True
return (firstCoin, secondCoin, thirdCoin)
main = print . sampleState threeCoins $ mkStdGen 21
firstCoin
secondCoin
thirdCoin
现在来自一元绑定(bind),
which is always monomorphic .
import Control.Monad (replicateM)
threeCoins :: RVar (Bool, Bool, Bool)
threeCoins = do
[firstCoin,secondCoin,thirdCoin] <- replicateM 3 $ uniform False True
return (firstCoin, secondCoin, thirdCoin)
关于haskell - 为什么 haskell 编译器可以推断出这种类型,而 ghci 不能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48006676/
基础问题 我要解决的基本问题是: 我有一个模板参数包 ArgTypes,我需要用包装在 std::optional 中的每个类型创建一个元组。例如:make_optional_tuple应该返回 st
我使用 createEntityAdapter 设置了一个简单的 redux store。初始状态包含实体、ID、状态、错误设置等 const carouselEventAdapter = creat
我有一些(遗留)代码,如下所示: void castFoo(string type, void* foo) { FooA* foo_a = NULL; FooB* foo_b = NULL;
我的代码是 const int *const ptrA = nullptr; auto *ptrB = &ptrA; 我对 const int *const ptrA 的看法是: (*
我目前正在尝试用 C++ 实现 XOR 链表。我尝试使用模板使其通用。编译时会弹出此错误,我无法解决这个问题。 我尝试使用模板在谷歌上搜索 XOR 链表,但到目前为止似乎还没有实现它。 异或链表.h:
我正在尝试找到一种方法来调用多个类成员函数,每个函数都有不同的参数,并且在调用前后会发生某些已知功能。 这个包装函数是我试过的,但是例如对它的最终调用不会编译错误: 'bool Wrapper(Wor
此代码在 上编译成功g++ ( Coliru ) ,但不是 Visual C++ ( rextester ) - 在线和我的桌面。 它是一个更大的 Visual Studio 2015 项目的简化版本
我正在尝试编写一个通用类,它传递一个键 key 对应于一组已知接口(interface)中的一个的键,稍后可以传递一个对象 thing 并类型安全地访问 thing[key]。这是我得到的: inte
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我是一名优秀的程序员,十分优秀!