我有以下函数来返回给定数字的因子对
factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)]
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0]
当我在ghci factorPairs 18
中调用该函数时,我的运行时错误
* Ambiguous type variable `a0' arising from a use of `it'
prevents the constraint `(Floating a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Floating Double -- Defined in `GHC.Float'
instance Floating Float -- Defined in `GHC.Float'
* In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
我可以在ghci
中对该函数进行硬编码 map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0]
并没有任何问题,但我似乎无法弄清楚为什么我的功能失败。我相信ghci试图告诉我它无法弄清楚要调用print
的类型,但我正在努力寻找解决方案。
答案 0 :(得分:5)
这与Haskell中重载数字文字的事实有关。当您在map(\x -> (x, div 18 x)) [y | y <- [1..(ceiling $ sqrt 18)], 18 `rem` y == 0]
中输入ghci
时,18
的参数sqrt
默认为Double
,其他Integer
为factorPairs:: (RealFrac a, Floating a, Integral a) => a -> [(a, a)]
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt n)], n `rem` y == 0]
。
但是,当你写
时n
您强制fromIntegral
的所有实例只有一种类型。然后,问题变成了没有默认的数字类型(实际上我认为通常是数字类型),它们满足所有这些约束,因此GHC会告诉你关于&#34;可能的实例&#34;它尝试。解决方案是添加factorPairs:: Integral a => a -> [(a, a)]
factorPairs n = map(\x -> (x, div n x)) [y | y <- [1..(ceiling $ sqrt $ fromIntegral n)], n `rem` y == 0]
并放宽约束:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ProPharmacyManagerW.Controls
{
class IconButton : Button
{
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register("Image", typeof(ImageSource), typeof(IconButton), new PropertyMetadata(null));
public static readonly DependencyProperty ImageHeightProperty = DependencyProperty.Register("ImageHeight", typeof(double), typeof(IconButton), new PropertyMetadata(double.NaN));
public static readonly DependencyProperty ImageWidthProperty = DependencyProperty.Register("ImageWidth", typeof(double), typeof(IconButton), new PropertyMetadata(double.NaN));
public static readonly DependencyProperty HoverColorProperty = DependencyProperty.Register("ColorHover", typeof(SolidColorBrush), typeof(IconButton), new PropertyMetadata(Brushes.LightGray));
public static readonly DependencyProperty PressedColorProperty = DependencyProperty.Register("ColorPressed", typeof(SolidColorBrush), typeof(IconButton), new PropertyMetadata(Brushes.Gray));
public static readonly DependencyProperty DisabledColorProperty = DependencyProperty.Register("ColorDisabled", typeof(SolidColorBrush), typeof(IconButton), new PropertyMetadata(Brushes.Gray));
static IconButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(IconButton), new FrameworkPropertyMetadata(typeof(IconButton)));
}
public ImageSource Image
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
public double ImageHeight
{
get { return (double)GetValue(ImageHeightProperty); }
set { SetValue(ImageHeightProperty, value); }
}
public double ImageWidth
{
get { return (double)GetValue(ImageWidthProperty); }
set { SetValue(ImageWidthProperty, value); }
}
public SolidColorBrush ColorHover
{
get { return (SolidColorBrush)GetValue(HoverColorProperty); }
set { SetValue(HoverColorProperty, value); }
}
public SolidColorBrush ColorPressed
{
get { return (SolidColorBrush)GetValue(PressedColorProperty); }
set { SetValue(PressedColorProperty, value); }
}
public SolidColorBrush ColorDisabled
{
get { return (SolidColorBrush)GetValue(DisabledColorProperty); }
set { SetValue(DisabledColorProperty, value); }
}
}
}
答案 1 :(得分:4)
摆脱类型错误的另一种方法是消除sqrt
的使用。由于Haskell是懒惰的,你可以简单地迭代[1..n]
,当你的除数大于你的商时停止。
factorPairs :: Integral a => a -> [(a, a)]
factorPairs n = takeWhile (uncurry (>=)) [ (n `div` d, d) | d <- [1..n], n `mod` d == 0]
uncurry (>=)
只是写\(q, d) -> q >= d
的一种奇特方式。
如果你以monadic形式写这个,你可以使用divMod
来获得商和余数,只需一个函数。
factorPairs n = takeWhile (uncurry (>=)) $ do
d <- [1..n]
let (q, r) = n `divMod` d
guard $ r == 0
return (q, d)